omrsafetyo
Enthusiast
Enthusiast

How to apply SDRS recommendations while adding a new disk

Jump to solution

I am trying to solve an issue where currently, we have rather large datastore clusters (many datastores) but each datastore is running with ~15% free space.  We try to keep this around that threshold to ensure we can take snapshots for backups, but as a minimum, we want each DS to have > 500GB free space.

So currently in VRO, I have a check that looks at a new VM build, or a request for an additional disk, or disk extension, and it checks all the Datastores in the DS cluster to ensure that some datastore has enough room to accommodate the full size of the requested disks, with the wiggle room (500GB) - basically, go find the DS with the most free space, and see if it has [requested size] + [500GB] space available.  If not, it fails the WF, and doesn't do the operation.  We have SDRS run on a 12 hour interval so as to prevent IO stunning mid-day.

I would like to improve this to use SDRS recommendations to add the disk where space is available automatically, and apply any other SDRS migrations that might be necessary to accommodate.   For instance, if I have ~1.3TB free on each DS, and someone requests a 1.5TB drive, I'd like to be able to create the drive while applying DRS - push around the disks until I have enough room to put a 1.5 TB disk.  Right now, we instead add a new DS to the cluster, and then re-submit the request.

It looks like I should be able to use applyStorageDrsRecommendation_Task to do this.  According to the documentation (https://www.vmware.com/support/orchestrator/doc/vro-vsphere65-api/html/VcStorageResourceManager.html ) I should be able to use this with the AddDisk API:

Applies a recommendation from the recommendation list. Each recommendation can be applied only once. In the case of CreateVm and CloneVm a VirtualMachine is returned. Other workflows don't have a return value.

Requires Resource.ApplyRecommendation privilege on the storage pod. Additionally, depending on the workflow where this API is called from, it may require the privileges of invoking one of following APIs:

CreateVm {@link vim.Folder#createVm}

AddDisk {@link vim.VirtualMachine#reconfigure}

RelocateVm {@link vim.VirtualMachine#relocate}

CloneVm {@link vim.VirtualMachine#clone}

However, I'm not sure how to apply that when I go to run my reconfigVM_Task.

I found this thread: Adding multiple disks using SDRS on VRO

With the solution code:

  1. for (var i in myarray) { 
  2.   myVcTask = managedObject.applyStorageDrsRecommendation_Task(myKey); 
  3.   actionResult = System.getModule("com.vmware.library.vc.basic").vim3WaitTaskEnd(myVcTask, progress, pollRate); 
  4.   ... // other code inside loop 

I'm just not sure what myKey represents.  Would that just be my config spec?  The documentation suggests the only parameter for the applyStorageDrsRecommendation_Task is a string.   I was just going to modify (a copy of) the built-in Add Disk WF for my purposes:

var configSpec = new VcVirtualMachineConfigSpec();

var deviceConfigSpecs = new Array();

var deviceConfigSpec;

// Add/Create the disk

deviceConfigSpec = System.getModule("com.vmware.library.vc.vm.spec.config.device").createVirtualDiskFlatVer2ConfigSpec(

diskSize, datastore, scsiControllerKey, diskIndex, VcVirtualDiskMode.fromString(diskMode.name), thinProvisioned );

deviceConfigSpecs[0] = deviceConfigSpec;

// List of devices

configSpec.deviceChange = deviceConfigSpecs;

// Launch the reconfigVM task

task = vm.reconfigVM_Task( configSpec );

Any suggestions?

0 Kudos
1 Solution

Accepted Solutions
omrsafetyo
Enthusiast
Enthusiast

Hello,


Yes, I do have this working at this time.

So I guess I should start at what my problem was.  My major issue ended up being SDRS settings in general.  As it turns out, SDRS will not return a recommendation when it cannot make a recommendation unless it adheres to its configured parameters.

So for instance, we had our SDRS threshold configured to 80%, but we were sitting at 85% full.  As it turns out, the issues I had in testing had to do with this - our scheduled jobs to apply DRS recommendations were also failing, for the same reason.  We ended up adjusting the threshold, and additionally moved to bigger datastores so that we can run them "thinner" (similar free space in raw GB/TB) while still having them at a higher % full.

With that said, my final solution was:

# invokeSDRSRecommendationWithChange

# INPUTS
# VC:VirtualMachine vm
# VC:ConfigSpecOperation configSpec

# VC:Datastore datastore

var storageSpec = new VcStoragePlacementSpec() ;

storageSpec.configSpec = configSpec;

storageSpec.type = 'reconfigure';

storageSpec.disallowPrerequisiteMoves = false; // default behavior

storageSpec.vm = vm;

myVcStorageDrsPodSelectionSpec = getVcStoragePodSelectionSpec(datastore,configSpec);

storageSpec.podSelectionSpec = myVcStorageDrsPodSelectionSpec;

var storageMgr = datastore.sdkConnection.storageResourceManager;

var clusterRecommendation = storageMgr.recommendDatastores(storageSpec);

var recommendationKey = clusterRecommendation.recommendations[0].key;

if(!recommendationKey) {

  System.log(clusterRecommendation.drsFault.reason);

  throw("recommendDatastores didn't return a recommendation");

}

task = storageMgr.applyStorageDrsRecommendation_Task( [ recommendationKey.toString() ] );

// Wait for the task to end.

var taskEnd = false;

var error;

var pollRate = 30;

var progress = true;

actionResult = System.getModule("com.vmware.library.vc.basic").vim3WaitTaskEnd(task,progress,pollRate);

System.log(actionResult);

return actionResult;

function getVmFolder(vm){

var parent = vm.parent;

while (parent !== null && ! (parent instanceof VcVmFolder)) {

parent = parent.parent;

}

System.log("VcVmFolder of VM: " + parent.name);

return parent;

}

function getDatstoreDatastoreCluster(datastore){

System.log("Finding parent StoragePod for " + datastore);

var p = datastore.parent; 

while (p != null) {

  System.log("Checking  " + p.name);

  if (p instanceof VcStoragePod) { 

    System.log("Datastore cluster found: " + p); 

    break; 

  } 

  p = p.parent; 

 

if (p == null) { 

  System.warn("No datastore cluster found!"); 

}

else {

return p;

}

}

function getVcStoragePodSelectionSpec(datastore,configSpec) {

var myVcVmPodConfigForPlacement = new VcVmPodConfigForPlacement();

var myVcPodDiskLocatorArray = new Array();

var myVcPodDiskLocator = new VcPodDiskLocator();

var myInitialVmConfig = new Array();

var myVcStorageDrsPodSelectionSpec = new VcStorageDrsPodSelectionSpec();

myVcPodDiskLocator.diskId = configSpec.deviceChange[0].device.key;

myVcPodDiskLocator.diskBackingInfo = configSpec.deviceChange[0].device.backing;

myVcPodDiskLocatorArray.push(myVcPodDiskLocator);

myVcVmPodConfigForPlacement.storagePod = getDatstoreDatastoreCluster(datastore); //myVcStoragePod;

myVcVmPodConfigForPlacement.disk = myVcPodDiskLocatorArray;

//myVcStorageDrsPodSelectionSpec.storagePod = getDatstoreDatastoreCluster(datastore)

myInitialVmConfig.push(myVcVmPodConfigForPlacement);

myVcStorageDrsPodSelectionSpec.initialVmConfig = myInitialVmConfig;

return myVcStorageDrsPodSelectionSpec;

}


I am calling the above action as follows:

var configSpec = new VcVirtualMachineConfigSpec();

var deviceConfigSpecs = new Array();

var deviceConfigSpec;

// Add/Create the disk

deviceConfigSpec = System.getModule("com.vmware.library.vc.vm.spec.config.device").createVirtualDiskFlatVer2ConfigSpec(

diskSize, datastore, scsiControllerKey, diskIndex, VcVirtualDiskMode.fromString(diskMode.name), thinProvisioned );

deviceConfigSpecs[0] = deviceConfigSpec;

// List of devices

configSpec.deviceChange = deviceConfigSpecs;

// Launch the reconfigVM task

System.getModule("org.mymodule.generic").invokeSDRSRecommendationWithChange(vm,configSpec,datastore);

This is really just a copy of the "Add disk" built-in workflow, with the "Add Disk" script modified, as far as I know, I only modified the following line in the script:

// Launch the reconfigVM task

task = vm.reconfigVM_Task( configSpec );


I will, lastly, note that as of right now this is working very well most of the time (especially when sufficient free space exists).  However, SDRS isn't particularly good for this task, as it applies recommendations somewhat in a vacuum, which will often cause timeouts.  For instance, lets say I have a 8TB datastore, and I want to add a 1TB VMDK to the datastore.  It is at 75% capacity, and in order to meet the reserve, it needs to migrate some items.  It may pick a 800GB vmdk, along with a couple smaller ones, and try to migrate it to a datastore that has sufficient free space for each individual disk at the time the recommendation is created, but is no longer valid after the smaller disks are migrated.  In this case, when it gets to the 800GB disk, it may no longer have sufficient space, and that operation will timeout, eventually causing an error in the above task.  I haven't revisited this problem yet, as I'm still waiting on getting our environment completely reconfigured with new SDRS settings, and bigger datastores so that I can move this into production - but it does work when it works and when the SDRS settings don't interfere!

Hope this helps!

View solution in original post

0 Kudos
2 Replies
KuChGi
Contributor
Contributor

Did you happen to get this working? I'm trying to do the exact same thing.

0 Kudos
omrsafetyo
Enthusiast
Enthusiast

Hello,


Yes, I do have this working at this time.

So I guess I should start at what my problem was.  My major issue ended up being SDRS settings in general.  As it turns out, SDRS will not return a recommendation when it cannot make a recommendation unless it adheres to its configured parameters.

So for instance, we had our SDRS threshold configured to 80%, but we were sitting at 85% full.  As it turns out, the issues I had in testing had to do with this - our scheduled jobs to apply DRS recommendations were also failing, for the same reason.  We ended up adjusting the threshold, and additionally moved to bigger datastores so that we can run them "thinner" (similar free space in raw GB/TB) while still having them at a higher % full.

With that said, my final solution was:

# invokeSDRSRecommendationWithChange

# INPUTS
# VC:VirtualMachine vm
# VC:ConfigSpecOperation configSpec

# VC:Datastore datastore

var storageSpec = new VcStoragePlacementSpec() ;

storageSpec.configSpec = configSpec;

storageSpec.type = 'reconfigure';

storageSpec.disallowPrerequisiteMoves = false; // default behavior

storageSpec.vm = vm;

myVcStorageDrsPodSelectionSpec = getVcStoragePodSelectionSpec(datastore,configSpec);

storageSpec.podSelectionSpec = myVcStorageDrsPodSelectionSpec;

var storageMgr = datastore.sdkConnection.storageResourceManager;

var clusterRecommendation = storageMgr.recommendDatastores(storageSpec);

var recommendationKey = clusterRecommendation.recommendations[0].key;

if(!recommendationKey) {

  System.log(clusterRecommendation.drsFault.reason);

  throw("recommendDatastores didn't return a recommendation");

}

task = storageMgr.applyStorageDrsRecommendation_Task( [ recommendationKey.toString() ] );

// Wait for the task to end.

var taskEnd = false;

var error;

var pollRate = 30;

var progress = true;

actionResult = System.getModule("com.vmware.library.vc.basic").vim3WaitTaskEnd(task,progress,pollRate);

System.log(actionResult);

return actionResult;

function getVmFolder(vm){

var parent = vm.parent;

while (parent !== null && ! (parent instanceof VcVmFolder)) {

parent = parent.parent;

}

System.log("VcVmFolder of VM: " + parent.name);

return parent;

}

function getDatstoreDatastoreCluster(datastore){

System.log("Finding parent StoragePod for " + datastore);

var p = datastore.parent; 

while (p != null) {

  System.log("Checking  " + p.name);

  if (p instanceof VcStoragePod) { 

    System.log("Datastore cluster found: " + p); 

    break; 

  } 

  p = p.parent; 

 

if (p == null) { 

  System.warn("No datastore cluster found!"); 

}

else {

return p;

}

}

function getVcStoragePodSelectionSpec(datastore,configSpec) {

var myVcVmPodConfigForPlacement = new VcVmPodConfigForPlacement();

var myVcPodDiskLocatorArray = new Array();

var myVcPodDiskLocator = new VcPodDiskLocator();

var myInitialVmConfig = new Array();

var myVcStorageDrsPodSelectionSpec = new VcStorageDrsPodSelectionSpec();

myVcPodDiskLocator.diskId = configSpec.deviceChange[0].device.key;

myVcPodDiskLocator.diskBackingInfo = configSpec.deviceChange[0].device.backing;

myVcPodDiskLocatorArray.push(myVcPodDiskLocator);

myVcVmPodConfigForPlacement.storagePod = getDatstoreDatastoreCluster(datastore); //myVcStoragePod;

myVcVmPodConfigForPlacement.disk = myVcPodDiskLocatorArray;

//myVcStorageDrsPodSelectionSpec.storagePod = getDatstoreDatastoreCluster(datastore)

myInitialVmConfig.push(myVcVmPodConfigForPlacement);

myVcStorageDrsPodSelectionSpec.initialVmConfig = myInitialVmConfig;

return myVcStorageDrsPodSelectionSpec;

}


I am calling the above action as follows:

var configSpec = new VcVirtualMachineConfigSpec();

var deviceConfigSpecs = new Array();

var deviceConfigSpec;

// Add/Create the disk

deviceConfigSpec = System.getModule("com.vmware.library.vc.vm.spec.config.device").createVirtualDiskFlatVer2ConfigSpec(

diskSize, datastore, scsiControllerKey, diskIndex, VcVirtualDiskMode.fromString(diskMode.name), thinProvisioned );

deviceConfigSpecs[0] = deviceConfigSpec;

// List of devices

configSpec.deviceChange = deviceConfigSpecs;

// Launch the reconfigVM task

System.getModule("org.mymodule.generic").invokeSDRSRecommendationWithChange(vm,configSpec,datastore);

This is really just a copy of the "Add disk" built-in workflow, with the "Add Disk" script modified, as far as I know, I only modified the following line in the script:

// Launch the reconfigVM task

task = vm.reconfigVM_Task( configSpec );


I will, lastly, note that as of right now this is working very well most of the time (especially when sufficient free space exists).  However, SDRS isn't particularly good for this task, as it applies recommendations somewhat in a vacuum, which will often cause timeouts.  For instance, lets say I have a 8TB datastore, and I want to add a 1TB VMDK to the datastore.  It is at 75% capacity, and in order to meet the reserve, it needs to migrate some items.  It may pick a 800GB vmdk, along with a couple smaller ones, and try to migrate it to a datastore that has sufficient free space for each individual disk at the time the recommendation is created, but is no longer valid after the smaller disks are migrated.  In this case, when it gets to the 800GB disk, it may no longer have sufficient space, and that operation will timeout, eventually causing an error in the above task.  I haven't revisited this problem yet, as I'm still waiting on getting our environment completely reconfigured with new SDRS settings, and bigger datastores so that I can move this into production - but it does work when it works and when the SDRS settings don't interfere!

Hope this helps!

0 Kudos