vSphere CreateContainerView/RetrievePropertiesEx 仅返回 100 个对象

vSphere CreateContainerView/RetrievePropertiesEx is only returning 100 Objects

我用的是nodejs,node代码很简单(这里用了一些民间故事,但是task类似于promise):

const connect = (vcenter) => {
    return new Task( (reject, resolve) => {
        const Vsphere = require('vsphere');
        const vc = new Vsphere.Client(vcenter, 'me', 'myPass', false);

        vc.once('ready', () => resolve(vc));
        vc.once('error', reject);
    })
}
const getVirtualMachines = (vc) => {
    return new Task( (reject, resolve) => {
        const rootFolder = vc.serviceContent.rootFolder;
        const vms =  vc.getMORefsInContainerByType( rootFolder, 'VirtualMachine');
        vms.once('result', resolve)
        vms.once('error', reject)
    })
}

connect(vcenterIp).
    chain(getVirtualMachines).
    // SNIP (this isn't significant)
    fork(e2,f2)

并导致发送这些请求

CreateContainerView
{
   "_this": {
      "attributes": {
         "type": "ViewManager"
      },
      "$value": "ViewManager"
   },
   "container": {
      "attributes": {
         "type": "Folder"
      },
      "$value": "group-d1"
   },
   "type": "VirtualMachine",
   "recursive": true
}



RetrievePropertiesEx
{
   "_this": {
      "attributes": {
         "type": "PropertyCollector"
      },
      "$value": "propertyCollector"
   },
   "specSet": [
      {
         "attributes": {
            "xsi:type": "PropertyFilterSpec"
         },
         "propSet": [
            {
               "attributes": {
                  "xsi:type": "PropertySpec"
               },
               "type": "VirtualMachine",
               "all": true
            }
         ],
         "objectSet": [
            {
               "attributes": {
                  "xsi:type": "ObjectSpec"
               },
               "obj": {
                  "attributes": {
                     "type": "ContainerView"
                  },
                  "$value": "session[520e031b-3c15-9c1d-408a-45ab98bde1dc]52dfe626-a128-c94f-8c4c-df52a68d97c0"
               },
               "skip": true,
               "selectSet": [
                  {
                     "attributes": {
                        "xsi:type": "TraversalSpec"
                     },
                     "type": "ContainerView",
                     "path": "view",
                     "skip": false
                  }
               ]
            }
         ]
      }
   ],
   "options": {}
}

哪个 returns

{ returnval: 
   { token: '0',
     objects: 
      [ [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object] ] } }

我看到的问题是 API 仅 returning 100 个项目,而我的环境中有超过 100 个虚拟机。

我真的想要查询 return 我所有的 VM


更新 1:

To invoke a single property collection operation, call the RetrievePropertiesEx method. The example application passes the populated PropertyFilterSpec and an empty options structure to the method. The default for the RetrieveOptions.maxObjects specifies that no maximum for the number of objects that can be returned is set. The PropertyCollector can impose a maximum. If the number of collected objects is greater than the maximum, the PropertyCollector returns a token value in the RetrieveResult data object and this token is used to retrieve the remaining properties using the ContinueRetrievePropertiesEx API method

https://pubs.vmware.com/vsphere-50/index.jsp?topic=%2Fcom.vmware.wssdk.pg.doc_50%2FPG_Ch5_PropertyCollector.7.5.html


更新 2

好的,看看 returned 结果 vSPehere return 给我一个令牌代码。并且 node-vsphere 库不会检索所有结果。我需要想出一种方法来一步得到所有结果。

我需要跟进这个请求

ContinueRetrievePropertiesEx
{
   "_this": {
      "attributes": {
         "type": "PropertyCollector"
      },
      "$value": "propertyCollector"
   },
   "token": "0"
}

这里是我如何使用库完成此操作的:

const connect = (vcenter) => {
    return new Task( (reject, resolve) => {
        const Vsphere = require('vsphere');
        const vc = new Vsphere.Client(vcenter, 'xyz\tbrown', 'ijhi', false);

        vc.once('ready', () => resolve(vc));
        vc.once('error', reject);
    })
}

const getVirtualMachines = (vc) => {
    return new Task( (reject, resolve) => {
        const rootFolder = vc.serviceContent.rootFolder;
        const vms =  vc.getMORefsInContainerByType( rootFolder, 'VirtualMachine');
        vms.once('result', (initial) =>{
            if(initial.returnval.token == undefined) {
                resolve(initial)
                return
            }else {
                const thisReceiveAll = receiveAll(reject, resolve)
                thisReceiveAll(vc, initial)
            }
        })
        vms.once('error', reject)
    })
}

const receiveAll = (reject, resolve) => (vc, initial) => {
    const executeContinueReceive = function executeContinueReceive(previous) {
        const args = {
            _this: {"attributes":{"type":"PropertyCollector"},"$value":"propertyCollector"},
            token: previous.returnval.token
        }
        vc.vc.runCommand('ContinueRetrievePropertiesEx', args).once('result', function(current){
            const previousObjects = previous.returnval.objects
            const currentObjects = current.returnval.objects
            const allObjects = previousObjects.concat(currentObjects)

            current.returnval.objects = allObjects
            if(current.returnval.token == undefined) {
                resolve(current);
                return
            }
            return executeContinueReceive(current)

        }).once('error', reject);
    }
    executeContinueReceive(initial)
}

基本上当我检索初始结果集并检查令牌时。如果令牌在那里,我输入一个递归 "receiveAll" 函数,该函数调用 runCommand('ContinueRetrievePropertiesEx', args) 并附加其结果。最后再次检查令牌,然后返回结果或进行另一个递归调用……也许这应该移回库中

您可以简单地使用 RetrieveProperties,不需要进行任何类型的遍历。