Beginning
Today, I’ll configure a storage DRS cluster in vCenter using VCF Orchestrator.
The goal
To cover the most common functionality and make it as general and generic as possible.
Something like that…

Let’s see how to get there. I wanted to:
- Support multiple vCenters.
- Support multiple datastore clusters.
- Support default and most common settings adjustments.
- Provide the defaults where applicable.
vCenters
To get all the vCenters and show them in the custom form’s dropdown box, I am using a simple function as an action element, looking for all objects of type VC:SdkConnection
and returning it as an array, because that’s what the dropdown box is expecting.
/**
*
* @return {Array/string}
*/
(function () {
const sdkConnections = Server.findAllForType('c') as VcSdkConnection[];
const vcNames = sdkConnections.map(vc =>
vc.id
);
return vcNames;
});
Datastore clusters
To get all available clusters, the idea is the same (to write a function in the action element), but the code, of course, is different.
First, I need to get the SDK connection (vCenter) as an object. For that, I am using the function I already wrote called getVcSdkConnectionByName
, which can be found here. Once I have it, I can use a built-in method called getAllVimManagedObject
and provide a StoragePod
(which is a datastore cluster in API language) as a managed object I am looking for. This method returns an array of objects (datastoreClusters
variable), so I should get all the available datastore clusters in that vCenter.
If this array is not empty (important to check), I am looping through and get the names to show them in the workflow dropdown box.
/**
* @param {string} vCenter - vCenter name
*
* @return {Array/string}
*/
(function (vCenter) {
if (!vCenter) return [""];
let datastoreClusters = [];
if (vCenter) {
const sdkConnection = System.getModule('com.examples.vmware_aria_orchestrator_examples.actions')
.vcSdkManagement()
.VcSdkManagement.prototype.getVcSdkConnectionByName(vCenter);
datastoreClusters = sdkConnection.getAllVimManagedObjects("StoragePod", null, null);
}
if (datastoreClusters.length !== 0) {
let datastoreClusterNames = [];
for (var i = 0; i < datastoreClusters.length; i++) {
datastoreClusterNames.push(datastoreClusters[i].name);
}
return datastoreClusterNames;
}
});
The logic
Let’s think… To do any manipulation with a datastore cluster, there are a few requirements that must be defined:
StorageResourceManager
VcStoragePod
VcStorageDrsConfigSpec
And more, based on how many use cases should be covered. In my case, I need those two more, because I want to be able to control DRS load balancing features.
VcStorageDrsIoLoadBalanceConfig
-
VcStorageDrsSpaceLoadBalanceConfig
Therefore, my brand new DatastoreClusterManagement
class looks like that:

DatastoreClusterManagement
classFind storage pod
First thing first. To modify a datastore cluster, I should find it and return its object. The name of the cluster I am getting from the workflow’s form and passing to the findStoragePod
as storagePodName
argument.
Now, I can use vCenter.getAllVimManagedObjects('StoragePod', [], "xpath:name[matches(.,'" + storagePodName + "')]")
to find the object.
It is a best practice to use
xpath
for a global searches/filters.
getAllVimManagedObjects
always returns an arrays. Therefore, I want to make sure it’s not empty and its unique.
private findStoragePod(vCenter: VcSdkConnection, storagePodName: string): VcStoragePod {
const storagePods = vCenter.getAllVimManagedObjects('StoragePod', [], "xpath:name[matches(.,'" + storagePodName + "')]");
if (storagePods.length === 0) {
throw new Error(`Storage Pod with name ${storagePodName} not found.`);
}
if (storagePods.length > 1) {
throw new Error(`Multiple Storage Pods found with name ${storagePodName}. Please specify a unique name.`);
}
return storagePods[0] as VcStoragePod;
}
findStoragePod
method
Build storage DRS config spec
To build a spec, I need a few things:
- Define a spec using a
VcStorageDrsConfigSpec()
class. - Define a pod config using a
VcStorageDrsPodConfigSpec
class. - Have all the values I want to set by getting them from the custom form.
To accomplish that, let’s create a new method called buildStorageDrsConfigSpec
and implement the necessary logic. All the supported parameters of podConfig
can be found in the VCF Orchestrator’s API. I’ve only included the parameters that I needed.
const spec = new VcStorageDrsConfigSpec();
const podConfig = new VcStorageDrsPodConfigSpec();
const spaceLoadBalanceConfig = { minSpaceUtilizationDifference, spaceThresholdMode, freeSpaceThresholdGB, spaceUtilizationThreshold };
podConfig.defaultVmBehavior = defaultVmBehavior;
podConfig.ioLoadBalanceConfig = this.buildIoLoadBalanceConfig(ioLoadImbalanceThreshold, ioLatencyThreshold);
podConfig.spaceLoadBalanceConfig = this.buildSpaceLoadBalanceConfig(spaceLoadBalanceConfig);
podConfig.ioLoadBalanceEnabled = ioLoadBalanceEnabled;
podConfig.defaultIntraVmAffinity = defaultIntraVmAffinity;
podConfig.automationOverrides = new VcStorageDrsAutomationConfig();
podConfig.loadBalanceInterval = loadBalanceInterval;
podConfig.enabled = isEnabled;
spec.podConfigSpec = podConfig;
return spec;
buildStorageDrsConfigSpec
method
The workflow
The scriptable task in the workflow itself is pretty simple:
- Get VC instance object
const sdkConnection: VcSdkConnection = System.getModule('com.examples.vmware_aria_orchestrator_examples.actions')
.vcSdkManagement()
.VcSdkManagement.prototype.getVcSdkConnectionByName(vCenter);
- Define new instance of
DatastoreClusterManagement
class
const datastoreCluster = new DatastoreClusterManagement();
- Pass all the variables and trigger the configuration
const task = datastoreCluster.configureStorageDrsForPod(
{ vc: sdkConnection, datastoreClusterName, defaultVmBehavior, ioLoadImbalanceThreshold, ioLatencyThreshold, minSpaceUtilizationDifference, spaceThresholdMode, freeSpaceThresholdGB, spaceUtilizationThreshold, ioLoadBalanceEnabled, defaultIntraVmAffinity, loadBalanceInterval, isEnabled });
System.getModule("com.vmware.library.vc.basic").vim3WaitTaskEnd(task, true, 2);
Tests
Let’s start the workflow. It is starting with pre-defined default values, tips for the operator, and smart selections. In that example, Space Threshold Mode can be either Utilization or Free Space. If Utilization is selected, the value will be Space Utilization Threshold.

If Free Space is selected, it switches to Free Space mode, and the Space Utilization Threshold input disappears.

Run the workflow. In the logs, I can see the selected vCenter was found, and the cluster was reconfigured successfully.

The same is visible on the vCenter side. All the provided values were set correctly.

Summary
Today, we witnessed another excellent instance of utilizing Orchestrator to automate and control of configuration changes.
For instance, I can set the minimum and maximum values permitted for thresholds, following to the company’s policies. This task becomes significantly challenging when relying purely on the vCenter’s GUI.
Source Code
The source code with the unit tests can be found here.
The vRO package is also available here and the external ECMASCRIPT package here.
All packages should be imported
💡
I also want to hear from you about how I can improve my topics! Please leave a comment with the following:
– Topics you’re interested in for future editions
– Your favorite part or take away from this one
I’ll do my best to read and respond to every single comment!