VMware Aria Automation Orchestrator

 View Only
  • 1.  Finding VMs and return as VC:Virtual Machine object

    Posted Apr 08, 2024 12:16 PM

    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



  • 2.  RE: Finding VMs and return as VC:Virtual Machine object

    Posted Apr 08, 2024 08:32 PM

    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;
      }
    });

     

     

     

     

     

     



  • 3.  RE: Finding VMs and return as VC:Virtual Machine object

    Posted Apr 09, 2024 07:06 AM

    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



  • 4.  RE: Finding VMs and return as VC:Virtual Machine object

    Posted Apr 09, 2024 09:12 AM

    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*/


  • 5.  RE: Finding VMs and return as VC:Virtual Machine object

    Posted Apr 10, 2024 07:26 AM

    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?



  • 6.  RE: Finding VMs and return as VC:Virtual Machine object

    Posted Apr 10, 2024 12:40 PM

    What you want to do there will certainly work (indeed, the code provided by  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



  • 7.  RE: Finding VMs and return as VC:Virtual Machine object

    Posted Apr 10, 2024 01:05 PM

    Very valid points were raised to review.

    Another way to consider: use the option number two, provided by , 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.



  • 8.  RE: Finding VMs and return as VC:Virtual Machine object

    Posted May 13, 2024 04:51 AM
    Hello,
    Here is my current solution :
    (mainly built from an assembly of code found in the workflow library examples)
    this actually is way faster (<5 seconds) than the plugin's vCenter.allVirtualMachines method (that was taking minutes for me too)
    (You might want to handle failure differently, I don't want this sub-workflow to stop in case it is called in a loop; so here I only log the error, and check for the 'VMObject' to be defined in the calling workflow)

    Get VM object from name

    Find all vm objects :

    Inputs :

    VMName - string

    Outputs :
    VMObjectsNames - Array/string
    Error - string

    Code :
    VMObjectsNames = [];

    var retry = 3;
    var undef = false;

    while (retry > 0)
    {
        vcs = VcPlugin.allSdkConnections;

        for each (var vc in vcs)
        {
            if (vc.viewManager)
            {
                var containerView = vc.viewManager.createContainerView(vc.rootFolder, ["VirtualMachine"], true);

                var oSpec = new VcObjectSpec();
                oSpec.obj = containerView.reference;
                oSpec.skip = true;

                var tSpec = new VcTraversalSpec();
                tSpec.name = 'traverseEntities';
                tSpec.path = 'view';
                tSpec.skip = false;
                tSpec.type = 'ContainerView';

                oSpec.selectSet = [tSpec];
     seconds
                 var propertySpecs = new Array();
               
                var pSpec = new VcPropertySpec();
                pSpec.type = "VirtualMachine";
                pSpec.pathSet = ["name"];
                propertySpecs.push(pSpec);

                var fs = new VcPropertyFilterSpec();
                fs.objectSet = [ oSpec ];
                fs.propSet = propertySpecs;

                var retrieveOptions = new VcRetrieveOptions();
                var propertyCollector = vc.propertyCollector.createPropertyCollector();

                try
                {
                    retrieveResult = propertyCollector.retrievePropertiesEx([fs], retrieveOptions);
                    do
                    {
                        if (typeof retrieveResult !== 'undefined' && retrieveResult !== null)
                        {
                            processObjects(retrieveResult);
                            if (retrieveResult.token !== 'undefined' && retrieveResult.token !== null)
                            {
                                retrieveResult = propertyCollector.continueRetrievePropertiesEx(retrieveResult.token);
                            } else
                            {
                                break;
                            }      
                        } else
                        {
                            break;
                        }
                    } while(true);
                } finally
                {
                    propertyCollector.destroyPropertyCollector();
                    containerView.destroyView();
                }
            } else
            {
                undef = true;
                break;
            }
        }
        if (undef == false)
        {
            retry = 0;
        }
    }

    if (VMObjectsNames.length < 1)
    {
        Error = "VM '" + VMName + "' is not reachable."
    }else
    {
        if (VMObjectsNames.length > 1)
        {
            Error = "There is more than one VM with that name ! (" + VMName + ")";
        }else
        {
           
            Error = "";
        }
    }

    function processObjects(retrieveResult)
    {
        var resultObjects = retrieveResult.objects;

        var pattern = new RegExp("^" + VMName + "$", "i");
        for (r in resultObjects)
        {
          var objContent = resultObjects[r];
          var id = objContent.obj.id;
          var type = objContent.obj.type;
          var props = objContent.propSet;
          for (p in props)
          {
            if (pattern.test(props[p].val))
            {
                var dunesId = "dunes://service.dunes.ch/CustomSDKObject?id='" + vc.id + ",id:" + id +"'&dunesName='VC:" + type + "'";
                VMObjectsNames.push(dunesId);
                break;
            }
          }
        }
    }

    Convert to object :

    Inputs :
    Error - string
    VMName - string
    VMObjectsNames - Array/string

    Outputs :
    VMObject - VC:VirtualMachine

    Code :
    if (Error == "")
    {
        VMObject = Server.fromUri(VMObjectsNames[0]);
        Server.log("Found " + VMObject.name + "(" + VMObject.id + ")");
    }else
    {
        Server.error(Error);
    }




  • 9.  RE: Finding VMs and return as VC:Virtual Machine object

    Posted May 13, 2024 05:02 AM

    I just found the example I used to come up with this, if you want to dig this method further :

    Library/vCenter/Virtual Machine management/Basic/Get virtual machines by name
    -> that is calling "Get virtual machines by name with PC"   <<<   "Convert to object" code is here...
    -> that is calling "Get vCenter entities by properties"   <<<   "Get VM object from name" code is here ;)