javavmwarevmware-sdk

Efficient way to traverse vcenter inventory and retrieve properties


I'm using yavijava and am required to traverse a vCenter and build a list of all hosts and VMs on it. For each host and VM, I need to retrieve a few properties such as the name, amount of RAM/CPU etc. My current code looks like this:

ManagedEntity[] hosts = new InventoryNavigator.searchManagedEntities("VirtualMachine");
for(int i=0;i<hosts.length;i++) {
  String name = hosts[i].getName();
  String xxx = hosts[i].XXXXX;
.....

And so on for the VMs too.

My question is, is there a more efficient way to do this considering the fact that there are a significant number of objects and each call (such as getName) sends a new request to vSphere?


Solution

  • You will want to build a property collector manually and depending on the inventory you will want to create an inventory system to relate the objects. I have a sample on github for clusters: https://github.com/yavijava/yavijava_cluster_prop_example

        RetrieveOptions options = new RetrieveOptions();
        options.setMaxObjects(100);
        String[] vmProps = new String[2];
        vmProps[0] = "name";
        vmProps[1] = "runtime.host";
        PropertySpec vmSpec = new PropertySpec();
        vmSpec.setAll(false);
        vmSpec.setType("VirtualMachine");
        vmSpec.setPathSet(vmProps);
    
        String[] hostProps = new String[4];
        hostProps[0] = "name";
        hostProps[1] = "summary.hardware.numCpuCores";
        hostProps[2] = "summary.hardware.cpuModel";
        hostProps[3] = "summary.hardware.memorySize";
        PropertySpec hostSpec = new PropertySpec();
        hostSpec.setAll(false);
        hostSpec.setType("HostSystem");
        hostSpec.setPathSet(hostProps);
    
        String[] clusterProps = new String[2];
        clusterProps[0] = "name";
        clusterProps[1] = "parent";
        PropertySpec clusterSpec = new PropertySpec();
        clusterSpec.setAll(false);
        clusterSpec.setType("ClusterComputeResource");
        clusterSpec.setPathSet(clusterProps);
    
        ObjectSpec oSpec = new ObjectSpec();
        oSpec.setObj(clusterMe.getMOR());
        oSpec.setSelectSet(com.vmware.vim25.mo.util.PropertyCollectorUtil.buildFullTraversalV4());
        PropertyFilterSpec[] pfSpec = new PropertyFilterSpec[1];
        pfSpec[0] = new PropertyFilterSpec();
    
        ObjectSpec[] oo = new ObjectSpec[1];
        oo[0] = oSpec;
    
        pfSpec[0].setObjectSet(oo);
        PropertySpec[] pp = new PropertySpec[3];
        pp[0] = vmSpec;
        pp[1] = hostSpec;
        pp[2] = clusterSpec;
    
        pfSpec[0].setPropSet(pp);
        RetrieveResult ret = serviceInstance.getPropertyCollector().retrievePropertiesEx(pfSpec, options);
    
        for (ObjectContent aRet : ret.getObjects()) {
            if(aRet.getObj().type.equalsIgnoreCase("ClusterComputeResource")) {
                printInfo(aRet);
            }
            if(aRet.getObj().type.equalsIgnoreCase("HostSystem")) {
                System.out.println("Host Info: ");
                printInfo(aRet);
                System.out.println("#######################");
            }
            if(aRet.getObj().type.equalsIgnoreCase("VirtualMachine")) {
                System.out.println("VirtualMachine: ");
                printInfo(aRet);
                System.out.println("#######################################");
            }
        }
    }
    
    private static void printInfo(ObjectContent objectContent) {
        // This is super generic here... To actually relate the objects so you
        // know which HostSystem a VirtualMachine lives on you need to implement
        // some kind of inventory system and use the MOR from the HostSystem
        // and the MOR from the vm.runtime.host
        for(DynamicProperty props: objectContent.getPropSet()) {
            System.out.println(props.val);
        }
    }