VMware Cloud Community
SistDip
Contributor
Contributor

Finding VMs and return as VC:Virtual Machine object

Hi all mates,

I need to recover some VMs and pass thrm to a workflow that changes their tags according to some backup rules.
We have Automation 8.13 and have about 4000 Vms in our vCenters.
I have a problem with this action:


var vms = new Array()
var vCenters=VcPlugin.allSdkConnections

for each (vCenter in vCenters){
 System.log("getVmFromSelectedVcs - vCenter.name: " + vCenter.name)
 if (vcToBeChecked.indexOf(vCenter.name) != -1) {                // just some of our vc
  System.log("Retrieving VMs ...")
  for each (vm in vCenter.allVirtualMachines) {
  //System.log("vm.name: " + vm.name)
  vms.push(vm)
 }
}

if(vms.length == 0 ){
throw("getVmFromSelectedVcs - No valid VMs found in " + vcToBeChecked)
} else {
System.log("getVmFromSelectedVcs - Returning " + vms.length + " VMs")
}

return(vms)                    //returning all VC:Virtual Machine found

It works fine but returning an array with 2500 Vms takes over 21 minutes to return the search result to the calling workflow.
Is there any way to make it faster? Should I just push the name of the VM?
I need your help!

LOG:

2024-04-08 11:10:45.385 +0000 INFO getVmFromSelectedVcs - vCenter.name: https://XXXXXXXXXXXX:443/sdk
2024-04-08 11:10:45.386 +0000 INFO Retrieving VMs ...
2024-04-08 11:10:45.409 +0000 INFO getVmFromSelectedVcs - Returning 2657 VMs
2024-04-08 11:33:55.985 +0000 INFO __item_stack:/item8
2024-04-08 11:36:20.307 +0000 INFO __item_stack:/item8/item7

Thanks
Pietro

0 Kudos
6 Replies
WhiteForEver
Enthusiast
Enthusiast

Hi there,


Yeah. Looping through is a very resourceful and time-consuming process. In addition, there is a limitation for 2500 objects returned by VC plugin.
The function below should do the job:

 

 

 

/**
 * Get VM object by name.
 *
 * {string} vmName - The name of the virtual machine to find.
 * @returns {VcVirtualMachine[]} - Array of VM objects.
 */
(function getVM(vmName) {
  /**
   *  {Array<VirtualMachine>}
   */
  var vms = VcPlugin.getAllVirtualMachines(null, "xpath:name[matches(.,'" + vmName + "')]");

  if (vms.length > 0) {
    return vms;
  }
});

 

 

 

 

 

 



----------------------------------------------------------
Thank you for your feedback regarding my response.
If it has successfully resolved your issue, kindly mark it as RESOLVED

Take a look at my blog below.
https://www.clouddepth.com
0 Kudos
SistDip
Contributor
Contributor

Hi mate,

thanks for the reply. I need to have all the machines present in some of our vcenters. We have about 15 vcenters and the workflow is launched only on some of them, decided by the user through the input form ( stored into vcToBeChecked variable ). 

The loop is fast, the problem is the return function.


Thanks

Pietro

Tags (1)
0 Kudos
eoinbyrne
Expert
Expert

Is there a reason you need to return all 2657 full VM Objects here? The breadth of that data (along with the other comment that the plugins limit return counts to 2500) could be why it's taking so long to return it all.

Since you want to run across *ALL* VMs in *some* vCenters & you're already looping over every applicable VM it might be better to avoid having that return array at all? Your Tag checking code could be called for the VM instead of pushing it to an array for return

// Guessing this is within an Action/function if you are returning something?

//var vms = new Array() // don't need this now
var vmCheckedCount = 0; // might be helpful to keep track of how many checks there were
var vCenters = VcPlugin.allSdkConnections

for each (vCenter in vCenters){
	System.log("getVmFromSelectedVcs - vCenter.name: " + vCenter.name)
	if (vcToBeChecked.indexOf(vCenter.name) != -1) { // just some of our vc
		System.log("Retrieving VMs ...")
		for each (vm in vCenter.allVirtualMachines) {
			//System.log("vm.name: " + vm.name)
			//vms.push(vm)
			System.log("Check tagging on VM - " + vm.name);
			
			**** <Your tagging code/action call here> ****
			
			vmCheckedCount++;
		}
	}
}
// You can always return void here too
return vmCheckedCount;

// Now you don't need this return
/*if(vms.length == 0 ){
	throw("getVmFromSelectedVcs - No valid VMs found in " + vcToBeChecked)
} else {
	System.log("getVmFromSelectedVcs - Returning " + vms.length + " VMs")
}

return(vms);                    //returning all VC:Virtual Machine found*/
0 Kudos
SistDip
Contributor
Contributor

This is a part of a bigger workflow, is an action element named getVmFromSelectedVcs and it's output will be the input of a "for each element" :

SistDip_0-1712733919387.png

I'm thinking about your hint, maybe I can return just the name of the vm found, and retrieve the full object in the second step.
There's a way to do that?

0 Kudos
eoinbyrne
Expert
Expert

What you want to do there will certainly work (indeed, the code provided by @WhiteForEver will do that part). You would probably need to modify (or create a copy of) the workflow "Backup Tagging" to let it accept a VM name String, then your "for-each" runs across the string array. Given the number of VMs you have to run over, that will be a lot of (~2500) invocations of that sub-workflow which will likely be expensive in performance & resource terms on the vRO server.

It seems like this approach could be improved though

- Modify your current workflow to process the VMs on a single vCenter, then create a wrapper workflow to call that using "for-each" with the list of those VCs you want to run across. This may solve your initial issue unless one vCenter in particular is managing most of the VMs. You would only need to change the current workflow and then create the "for-each" wrapper to call it

- (Personally, I'd use this variant) Drop the fist TWO elements of your current workflow & replace with a scriptable task. Then copy in the VM retrieval code you already have & also the code for the Tagging checks. Then you can run everything within a single workflow under one for loop where each VM is retrieved and checked for tags in one place. It will be a lot less expensive & probably quicker since no long lists of large Objects will be getting passed around & you won't be double-hitting the VCenters for each VM (once for the initial name lookup & again for the Object retrieval)

If you don't have time for lots of churn, go with your first instinct as it will definitely work, but, if you need to run this process a number of times a day I would recommend keeping an eye on the performance. For a one-off, I wouldn't worry 

 

-HTH

0 Kudos
WhiteForEver
Enthusiast
Enthusiast

Very valid points were raised to review.

Another way to consider: use the option number two, provided by @eoinbyrne, but on top of that, you can call REST API call from vRO to vCenter and get in a one shot all VMs, which has a particulate tag. This will be super fast. And the amount of returned objects will be less. Once the list of the VMs is here, you pass it to the Tags workflow and so on.



----------------------------------------------------------
Thank you for your feedback regarding my response.
If it has successfully resolved your issue, kindly mark it as RESOLVED

Take a look at my blog below.
https://www.clouddepth.com
0 Kudos