获取 ESXi 服务器所有的数据中心 Datacenter 的名称

时间:2022-04-10 15:17:51

遍历清单的层次结构或特定的节点对象总是从与会话关联的 ServiceInstance 开始,即清单的根对象。单个ESXi 服务器的清单层次结构如下图所示:
获取 ESXi 服务器所有的数据中心 Datacenter 的名称

对于一个独立的 ESX/ESXi 系统,仅支持单个 Datacenter,Datacenter 下包含四个子 Folder,这些 Folder 对应具体的实体节点资源(虚拟硬件资源)。

要从清单对象中获取资源对象信息,Datacenter 对象也是必须遍历的,所以对 Datacenter 的遍历同样很重要,获取到 Datacenter 对象信息后,就可以利用 Datacenter 来获取想要的子 Folder 虚拟资源对象信息。

具体的遍历清单思路:从清单根对象 ServiceInstance 开始,使用 TraversalSpec 结合属性收集器(property collector)来访问对象,使用其属性确定一个对象在层次结构中的位置。

另外,通过 MOB 浏览对象可以更直观的查看某个托管对象具体属性。
MOB 的使用方法可以参考根据 MOB/vSphere APIs 获取 ESXi 服务器证书这篇文章。

下面列出遍历 Datacenter 属性name值的代码,这里使用 List 进行保存,以便在vCenter 服务器中可以直接扩展:

private AbstractVmClientSessionVmApi vmClientSession = null;

public InventoryInfoApiSupport(AbstractVmClientSessionVmApi vmClientSession) {
  this.vmClientSession = vmClientSession;
}

/** * @Title: getDatacenterName * @Description: 获取出所有的数据中心 Datacenter的属性name的值 * @return retVal:数据中心名称集合。 * @version 1.0 * @throws Exception */
@Override
public List<String> getDatacenterName() throws Exception {
  List<String> retVal = new ArrayList<String>();
  ManagedObjectReference rootFolder = vmClientSession.getServiceContent().getRootFolder();
  try {
    // 获取数据中心遍历规范
    TraversalSpec tSpec = getDatacenterTraversalSpec();

    ObjectSpec objectSpec = new ObjectSpec();
    objectSpec.setObj(rootFolder);
    objectSpec.setSkip(Boolean.TRUE);
    objectSpec.getSelectSet().add(tSpec);

    // 设置遍历的属性路径
    PropertySpec propertySpec = new PropertySpec();
    propertySpec.setAll(Boolean.FALSE);
    propertySpec.getPathSet().add("name");
    propertySpec.setType("Datacenter");

    // 添加对象和属性声明到 PropertyFilterSpec。
    PropertyFilterSpec propertyFilterSpec = new PropertyFilterSpec();
    propertyFilterSpec.getPropSet().add(propertySpec);
    propertyFilterSpec.getObjectSet().add(objectSpec);

    List<PropertyFilterSpec> listfps = new ArrayList<PropertyFilterSpec>(1);
    listfps.add(propertyFilterSpec);

    // 检索属性对应的对象
    List<ObjectContent> listobcont = retrievePropertiesAllObjects(listfps);

    // 遍历对象中的 name 属性
    if (listobcont != null) {
      for (ObjectContent oc : listobcont) {
        String dcnm = null;
        List<DynamicProperty> dps = oc.getPropSet();
        if (dps != null) {
          for (DynamicProperty dp : dps) {
            dcnm = (String) dp.getVal();
            retVal.add(dcnm);
          }
        }
      }
    }
  } catch (SOAPFaultException sfe) {
    sfe.printStackTrace();
  } catch (Exception e) {
    e.printStackTrace();
  }
  return retVal;
}

根据MOB浏览对象属性,获取 Datacenter 遍历规范

/** * @Title: getDatacenterTraversalSpec * @Description: 获取 Datacenter 遍历规范 * @return * @version 1.0 */
private TraversalSpec getDatacenterTraversalSpec() {
  // SelectionSpec是TraversalSpec的一个引用。
  SelectionSpec sSpec = new SelectionSpec();
  sSpec.setName("VisitFolders");
  TraversalSpec traversalSpec = new TraversalSpec();
  // 给traversalSpec设置名称
  traversalSpec.setName("VisitFolders");
  // 从rootFolder开始遍历,rootFolder类型是Folder
  traversalSpec.setType("Folder");
  // rootFolder拥有childEntity属性,清单结构图中指向的便是Datacenter
  traversalSpec.setPath("childEntity");
  // false表示不对其本身进行收集,只对其下对象进行收集
  traversalSpec.setSkip(false);
  // 将sSpec添加到SelectionSpec集合中
  traversalSpec.getSelectSet().add(sSpec);
  return traversalSpec;
}

根据属性 检索要查询的对象信息

/** * @Title: retrievePropertiesAllObjects * @Description: 根据属性检索要查询的对象信息 * @param listpfs * @return * @throws Exception * @version 1.0 */
private List<ObjectContent> retrievePropertiesAllObjects(List<PropertyFilterSpec> listpfs) throws Exception {
  RetrieveOptions propObjectRetrieveOpts = new RetrieveOptions();
  List<ObjectContent> listobjcontent = new ArrayList<>();
  VimPortType vimPortType = this.vmClientSession.getVimPortType();
  ServiceContent serviceContent = this.vmClientSession.getServiceContent();
  try {
    // 检索属性
    RetrieveResult rslts =
        vimPortType.retrievePropertiesEx(serviceContent.getPropertyCollector(), listpfs, propObjectRetrieveOpts);
    if (rslts != null && rslts.getObjects() != null && !rslts.getObjects().isEmpty()) {
      listobjcontent.addAll(rslts.getObjects());
    }
    String token = null;
    if (rslts != null && rslts.getToken() != null) {
      token = rslts.getToken();
    }
    while (token != null && !token.isEmpty()) {
      rslts = vimPortType.continueRetrievePropertiesEx(serviceContent.getPropertyCollector(), token);
      token = null;
      if (rslts != null) {
        token = rslts.getToken();
        if (rslts.getObjects() != null && !rslts.getObjects().isEmpty()) {
          listobjcontent.addAll(rslts.getObjects());
        }
      }
    }
    return listobjcontent;
  } catch (Throwable e) {
      e.printStackTrace();
  }
}

测试:

/** * @Title: getDatacenterNameTest * @Description: 获取出所有的数据中心 * @throws Exception * @version 1.0 */
  @Test
  public void getDatacenterNameTest() throws Exception {
    URL url = new URL("https://192.168.1.xxx/sdk/vimService?wsdl");
    EsxiConnectionEntity esxiConnectionEntity = new EsxiConnectionEntity();
    esxiConnectionEntity.setPassword("123456");
    esxiConnectionEntity.setUrl(url);
    esxiConnectionEntity.setUserName("root");

    VmClientSession vmClientSession = VmClientSessionFactory.bulidVmClientSession(esxiConnectionEntity, "userId");
    List<String> dcNameList = vmClientSession.getEsxiApi().getInventoryInfoApi().getDatacenterName();

    for (String dcName : dcNameList) {
      System.out.println("数据中心名:" + dcName);
    }

    vmClientSession.close();
  }



参考
使用VMware VSphere WebService SDK进行开发 (一)——基本信息阐述

VMware vSphere Web Services SDK编程指南(六)- 6 Datacenter Inventory