This is the final part of the series, covering the completed workflow used to configure the VM recovery settings via the SRM API. As of SRM 8.2 it is now possible to set the recovery settings for VMs using workflows provided by the SRM vRO plugin (new post coming soon on this subject), however for earlier versions the approach laid out in this post is the only solution.
With a working process to login/out of the SRM server via the api (see part 4 for the background) and the SRM Server at the Protected Site connected to vRO as both a SOAP and a REST host it is time to look at the steps needed to complete the workflow.
Logging in to SRM
As mentioned in part 4 the operation to log in to SRM is being performed as a REST operation. We added the operation to the REST host at the end of part 4, the next step is to use the workflow provided by the REST plugin ‘Generate a new workflow from a REST Operation’ to create a new workflow which will execute the log in operation.
Once the workflow is created we need to edit it to so that we can pass additional headers and an updated content body when the operation is executed. Within the scripting element of the workflow locate the line ‘//Customize the request here’. Add the following lines of code after this heading to set the additional headers on the operation. These headers were captured in Fiddler on the login operation:
request.setHeader(“SOAPAction”, “urn:srm0/7.0”);
request.setHeader(“Content-Type”,”text/xml; charset=utf-8″);
We also need to change the content variable to be an input parameter, as we will be updating this value in an earlier workflow. Finally, we need to set the headers variable as an output parameter, since the authorization token will be returned by the operation in the headers we will need to be access the headers in a later workflow step to extract the token value.
Next we create a new workflow to wrap around our REST operation. I’ve named this workflow Log in to SRM and retrieve the session token. Within this workflow add a scripting element and set it’s inputs and outputs to match the screenshots below:


I’ve named the scripting element ‘Set content for REST call’. Within this scripting element add the following code, this is to set the content value that will be passed to SRM for the login operation and inject the correct username and password values into the operation.
Now add the REST operation workflow generated at the start of this post to the workflow after the scripting element. Set the inputs and outputs to match the screenshots below:


Finally add a second scripting element to the workflow, this time after the REST operation workflow. I’ve named this ‘Extract the session token’. The scripting element just needs a single input parameter which is mapped to the headers output of the REST operation workflow. It also needs a single output parameter, which is the token value we will extract from the headers passed in. Add the following code to the scripting element to retrieve the token value:
The completed workflow should look like the image below, with the inputs and outputs mapped as per the screenshots.



SOAP Operations
That’s the first part of the overall process completed. Next we need to create a series of workflows to cover the SOAP API operations we need to perform to collect the various pieces of information we will need in order to set the recovery settings on our VM. As we are working with the API all the values we use have the string, secure string, or number type and therefore we can’t reuse the values from the earlier parts of the workflow, such as the protection group object. This means we have to duplicate some of the steps we have already performed in order to collect the information in the format needed by the API.
Use the SOAP plugin workflow Generate a new workflow from a SOAP operation (located in Library\SOAP) to create a new workflow for each of the following SOAP operations. You can keep the default names for the generated workflows, however I prefer to name them based on the operation being performed and remove the ‘invoke…’ part of the name e.g. Get Protection Group Root Folder:
- GetProtectionGroupRootFolder
- GetProtectionGroup
- ListProtectedVms
- GetRecoveryPlanRootFolder
- GetRecoveryPlan
- GetRecoverySettings
- SetRecoverySettings
Once each of the workflows is created, edit each one in turn and add a new string input parameter to the workflow and name it token. Map the input parameter to the scripting element inside the workflow. The screenshots below show the GetProtectionGroupRootFolder SOAP operation workflow with the additional parameter added.


Now within the code of the scripting element locate the lines
System.log(“invoking ‘” + operation.name + “‘ operation…”);
var response = operation.invoke(request);
Add the following line of code to the scripting element before the lines above, i.e. before the operation is invoked. This will add the token value as a header to the request with the header name of Cookie to each of the operations when they are executed:
request.setHttpHeader(“Cookie”,token);
Once completed you should have a section of code like the screenshot below. The exact code for the setInParameter and addInParameterAttribute lines may be slightly different in your workflow, as this varies for each SOAP operation being executed.

Remember to do this for each of the SOAP operation workflows, so that each one takes the token as an additional input to the workflow and then sets the value as a Http Header on the operation.
The last change to be made to each of the workflows is to change the output parameters outHeaders and outParameters into attributes. In the next section of this post we will update the workflows to add new output parameters, but for now leave each workflow without any output parameters.
It’s also a good idea after testing to return to each of the workflows to comment out the lines at the end of the script which print the outHeaders and outParameters values to the log. Although each operation on its own does not produce excessive logging, when they are all combined into a single workflow it can produce a very busy log.
Capturing the required information from the operation outputs
Each SOAP Operation workflow returns two outputs currently
- outHeaders
- outParameters
Depending on the operation the value(s) we need to extract from the information returned by the operation will be contained in one of these parameters, and we will need to process the parameter value to extract just the value we need.
For example, here is an extract of the log showing the values returned by the GetProtectionGroupRootFolder operation.

We can see that the outHeaders parameter had no value, but the outParameters contained a single parameter named returnval, which had an attribute named type. In this example we want the value of the returnval(type) parameter, which is the name of the SRM Protection Group Root Folder. To extract this value we can use the getOutParameterAttribute() method provided by the SOAP plugin. We also need the value of the returnval parameter, which is the object type value associated with the SRM Protection Group Root Folder. This time we can use the getOutParameter() method provided by the SOAP plugin.
For each operation the values we need to extract are different, however the operation will always provide an outParameter value containing a parameter named returnval, which may or may not have additional attributes associated with it. You can see the structure of the outParameters value by looking at the operation under the SOAP host on the vRO inventory tab. For example, look at the screenshots below which show the GetProtectionGroupRootFolder and ListProtectedVms operations.

You can see that the first operation provides a parameter named returnval, which has a single attribute named type.

The second operation also provides a parameter named returnval, however this time it is an array of values. Each entry in the array contains a set of named attributes, such as vmName. In this case we would need to traverse the contents of the array to find the correct entry, and then retrieve the value of the named attribute we are interested in.
Armed with this information we need to update each of the SOAP operation workflows to retrieve the required output values, and assign these to output parameters so that the values can be passed between the various subworkflows we are using.
GetProtectionGroupRootFolder
Create two new String output parameters in the workflow named protectionGroupRootFolder and protectionGroupRootFolderType, and map them as outputs of the scripting element named ‘Scripting’ on the schema tab.
At the end of the current code within the ‘Scripting’ scripting element add the following lines of code to extract the Root Folder value and type value from the output of the operation and assign the values to our new workflow output parameters.
GetProtectionGroup
Edit the workflow and create two new String output parameters named protectionGroup and protectionGroupType. Map the new output parameters as outputs of the of the scripting element. Then add the following lines of code to the end of the current code in the scripting element to extract the values we need for the protection group.
ListProtectedVms
As with the previous workflows add two new String output parameters to the workflow. Name the parameters protectedVM and protectedVMType. Add the following lines of code to the end of the scripting element to retrieve the protected VM name and type values. Notice that we are telling vRO we want to use the 1st entry in the results array located at position 0 and then the name of the attribute we want to retrieve. We can always use the 1st value in this scenario as each VM is provisioned into a new SRM Protection Group by vRA, so there will only be a single VM in the array of results.
GetRecoveryPlanRootFolder
Add two new String output parameters to the workflow and name them recoveryPlanRootFolder and recoveryPlanRootFolderType. Map them as outputs to the scripting element and then add the following lines of code to the end of the scripting element.
GetRecoveryPlan
Add two new String output parameters to the workflow and name them recoveryPlan and recoveryPlanType. Map them as outputs to the scripting element and then add the following lines of code to the end of the scripting element.
GetRecoverySettings
This workflow requires several new output parameters creating to capture the current recovery setting parameters from the operation output. The parameters are listed below, and are of type String unless otherwise identified. Map each of these parameters as outputs on the scripting element.
- changeVersion (number)
- status
- localSiteUuid
- remoteSiteUuid
- localSiteDeviceId
- remoteSiteDeviceId
- recoveryPriority
- skipGuestShutdown (boolean)
- powerOffTimeoutSeconds (number)
- finalPowerState
- localFaultToleranceState (boolean)
- remoteFaultToleranceState (boolean)
- powerOnTimeoutSeconds (number)
- powerOnDelaySeconds (number)
Add the following section of code to the end of the scripting element. Note that if the recovery settings have not been updated since the VM was originally added to SRM then the changeVersion value will be an empty string. SRM will automatically increment the changeVersion when it applies the new recovery settings, it does not require the vRO workflow to increment this value when submitting new recovery settings.
The code also checks if the IP customisation settings have been defined on the VM previously and then extracts the details about the local and remote sites if they are set.
SetRecoverySettings
The final SOAP operation workflow does not require any additional input or output parameters, however there are some input parameters which can be ignored as they are not being used. For example, the IPV6 settings will not be altered and can therefore be removed from the SOAP operation. These parameters can be removed from the list of input parameters and the associated lines of code which set them as inputs to the SOAP operation removed from the scripting element.
The following parameters can be removed for my scenario:
- settings_D_prePowerOnCallouts_OB_0_CB__D_description
- settings_D_prePowerOnCallouts_OB_0_CB__D_uuid
- settings_D_postPowerOnCallouts_OB_0_CB__D_description
- settings_D_postPowerOnCallouts_OB_0_CB__D_uuid
- settings_D_vmIpCustomizationData_D_ipCustomizationMappings_OB_0_CB__D_ipCustomizationSpec_D_nicCustomizationSpecs_OB_0_CB__D_ipV6AddressSpecs_OB_0_CB__D_staticAddressInfo_D_address
- settings_D_vmIpCustomizationData_D_ipCustomizationMappings_OB_0_CB__D_ipCustomizationSpec_D_nicCustomizationSpecs_OB_0_CB__D_ipV6AddressSpecs_OB_0_CB__D_staticAddressInfo_D_gateways_OB_0_CB_
- settings_D_vmIpCustomizationData_D_ipCustomizationMappings_OB_0_CB__D_ipCustomizationSpec_D_nicCustomizationSpecs_OB_0_CB__D_ipV6AddressSpecs_OB_0_CB__D_staticAddressInfo_D_subnetPrefixLength
With these parameters removed the code within the scripting element can be updated as follows (remember to replace the first two lines with your own SOAP host reference id):
Retrieving Existing Network Settings
The SOAP operation workflows will provide us with the majority of the information we need, however there is an additional value which we need to retrieve from the vRA payload. In order to customise the IP settings of the VM we have to tell SRM which of the network adapters configured on the VM it should apply the values to. SRM identifies the network adapters inside the VM using the mac address value, and therefore we will need to retrieve the mac address of the primary network adapter from the payload.
In addition when customising the network settings we need to tell SRM the values to use for the following settings:
- DNS Suffix
- DNS Server List
Both of these values can be retrieved from the existing network settings of the VM via the vRA payload if they will remain unchanged, otherwise you will need to specify the values to use within the workflow or via another method such as vRA custom properties. In my scenario the values will remain unchanged, as the VM is set to use DNS servers from both sites when it is built.
The last value that needs to be specified is the new IP address to use for the VM at the Recovery Site. Depending on your setup you may be able to use Subnet Mappings in SRM to determine the new address to use, however for my scenario IP addresses are allocated using a 3rd party IPAM tool and the vRA event broker. Therefore, I will allocate an additional IP address to the VM during provisioning and store this value, the gateway address and the subnet mask for the recovery network as vRA custom properties so that they can be retrieved from the payload.
Creating the workflow
The approach I am using is to create a new workflow to contain all of the REST and SOAP operations required to set the recovery settings on the VM. This workflow is then added to the parent workflow used in the earlier parts of this blog series. Taking this approach allows the setting of the recovery settings to be used as a separate workflow in the future if required, without having to set up new inventory objects within SRM.
Retrieving extra values from the payload
The workflow created in parts 1-3 of this series contains the scripting element to retrieve values from the vRA payload. As mentioned earlier, there are some extra values relating to the network configuration of the VM that are also stored within the vRA payload which we require. Now, you can create a new scripting element within the workflow we are about to create in this part of the series to retrieve these values, however my personal preference is to perform these steps in one place only within a workflow. Therefore, I have updated the ‘Retrieve values from payload’ scripting element in the workflow created in parts 1-3 to extract the MAC address of the network adapter and the recovery network address settings allocated to the VM.
Configuring the workflow inputs
Create a new workflow and name it Set Recovery Settings on the VM. Add input parameters to the workflow for the following values, which all have the type of string unless otherwise indicated:
- macAddress
- ipAddress
- subnetMask
- gateway
- localUsername
- localPassword (SecureString)
- remoteUsername
- remotePassword (SecureString)
- vm (VC:VirtualMachine)
- recoveryPlanName
- protectionGroupName
It should look like the screenshot below once complete. The names used for the ipAddress, subnetMask and gateway parameters reflect the fact that they are used as part of the SRM customisation spec for the network adapter and are an abbreviated version of the parameter names provided by the SOAP operation.

Add the Login operation workflow
On the schema tab of the Set Recovery Settings on VM workflow add the workflow we created earlier for logging in to SRM (Login to SRM and Retrieve Session Token). Configure the inputs/output parameters to map to new attributes and the input parameters created as per the screenshots below:


The contentTemplate attribute could also be configured as an input parameter if preferred, however as I want to be able to run the Set Recovery Settings on VM workflow separately I have chosen to make it an attribute and store the value inside this workflow. Set the contentTemplate attribute value to the following string, which is the REST operation content we captured using Fiddler in part 4 with placeholders for the username and password values.
Add attributes ready for the SOAP operations
Each of the SOAP operation workflows has at least one input parameter which will need to be mapped to an attribute within the Set Recovery Settings on VM workflow. Whilst we could create these attributes when adding the relevant workflows, it will actually be easier to create them and set their values first. This is because each workflow has the same name for its input parameters _this and _this_OP_type_CP_. By creating the attributes first we can easily map each of these input parameters to the correct attributes, with the correct values when we add the workflow.
If you remember from part 4 of this series, each _this and _this_OP_type_CP_ value represents an object class within the SRM api. This means each of the attributes we create will be String values.
Create the following attributes within the workflow. I have named the attributes based on the SOAP operation name or API object they are associated with, using a suffix of Type for the _this_OP_type_CP_ parameter:
- getSRMProtectionGroupRootFolderValue
- getSRMProtectionGroupRootFolderType
- protectionGroupRootFolder
- protectionGroupRootFolderType
- protectionGroup
- protectionGroupType
- getSRMRecoveryPlanRootFolderValue
- getSRMRecoveryPlanRootFolderType
- recoveryPlanRootFolder
- recoveryPlanRootFolderType
- recoveryPlan
- recoveryPlanType
- protectedVM
- protectedVMType
Set the value of the following attributes to SrmProtection
- getSRMProtectionGroupRootFolderValue
- getSRMProtectionGroupRootFolderType
Set the value of the following attributes to SrmRecovery
- getSRMRecoveryPlanRootFolderValue
- getSRMRecoveryPlanRootFolderType
Add the SOAP operation workflows
Now we need to add the workflows for the various SOAP operations to the schema. The order in which the workflows are executed is important, as each operation will retrieve values that are consumed by later operations. On the schema tab of the Set Recovery Settings on VM workflow add the workflow that performs the GetProtectionGroupRootFolder operation. Map the input parameters of the workflow to the getSRMProtectionGroupRootFolderValue, getSRMProtectionGroupRootFolderType and token attributes. It should look like the screenshot below once complete.

On the Out tab map the outputs of the workflow to the protectionGroupRootFolder and protectionGroupRootFolderType attributes that we created earlier.
Next add the GetRecoveryPlan operation workflow to the schema and map the inputs to the protectionGroupRootFolder, protectionGroupRootFolderType and token attributes. It should look like the screenshot below when complete.

On the Out tab map the outputs to the protectionGroup and protectionGroupType attributes.
The next workflow to add is the ListProtectedVMs operation. The inputs should be mapped to the protectionGroup, protectionGroupType and token attributes. The outputs should be mapped to the protectedVM and protectedVMType attributes.
Now add the GetRecoveryPlanRootFolder operation and map the inputs to the getSRMRecoveryPlanRootFolder, getSRMRecoveryPlanRootFolderType and token attributes. The outputs should be mapped to the recoveryPlanRootFolder and recoveryPlanRootFolderType attributes.
Next, add the GetRecoveryPlan operation and map the inputs as per the screenshot below:

The protectionGroupName value will be the same value used in the workflow to create the protection group. Map the outputs of the workflow to the recoveryPlan and recoveryPlanType attributes.
Add the GetRecoverySettings workflow and map the inputs and outputs as per the screenshots below:


The last of the SOAP operations to be added is the SetRecoverySettings workflow. Map the input parameters as per the screenshot below:

Now add the Logout REST operation workflow to the schema. Map the contentTemplate input parameter to a new attribute named contentTemplateLogout and the token input parameter to the token attribute.
Before closing the workflow we need to set the predefined values for the workflow attributes. These are values like the contentTemplate for the logout operation and the boolean variables which need to have a default value set. For the contentTemplateLogout value use the following code:
Save and close the workflow.
Combining the workflows
The final steps are to edit the workflow created in the earlier parts of this series and add our new workflow. Before adding the workflow we need to add a new scripting element to the end of the Configure DR for the VM workflow schema. Add the protectionGroup and recoveryPlan attributes as inputs to the new scripting element, and create new outputs to the scripting element named recoveryPlanName and protectionGroupName, both with a type of String.
Within the scripting element add the following lines of codes to retrieve the names of the Protection Group and Recovery Plan.
Now add the Set Recovery Settings on VM workflow to the schema after the scripting element. Map the input parameters as per the screenshot below:

vRA Blueprint configuration
Now that the workflow is complete, it can be published into vRA as an event broker subscription. I’m using the Machine Provisioning lifecycle event topic, with the conditions set to:
- Lifecycle state name equals VMPS.MasterWorkflow32.MachineProvisioned
- Lifecycle state phase equals POST
- ${data~machine~properties~SRM.Required} equals true
These conditions ensure that the workflow doesn’t execute until after vRA has finished creating the VM in vCenter, and only if the value of the SRM.Required custom property is set to true.
The SRM.Required custom property is added to my blueprint in vRA as a tick box on the request form to allow users to select whether SRM protection is required. Finally, don’t forget to add the Extensibility.Lifecycle.Properties.VMPSMasterWorkflow32.MachineProvisioned custom property to the blueprint to tell vRA to pass the payload values to vRO when the event broker subscription is activated.