遍历清单的层次结构或特定的节点对象总是从与会话关联的 ServiceInstance 开始,即清单的根对象。单个ESXi 服务器的清单层次结构如下图所示:
对于一个独立的 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