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

来源:互联网 发布:winxp哪个版本适合编程 编辑:程序博客网 时间:2024/06/05 18:40

原文地址:http://blog.csdn.net/u013256816/article/details/49779029

网上对于VSphere WebService SDK的介绍比较少(至少我能查到的资料比较少),官方提供的也是英文版的api,而且没有注明使用方法。最近接触到关于VSphere WebService SDK的开发,刚开始也是烦躁,比如要获取一个cpu使用情况的信息,按照惯例,API应该提供类似:long getCpuUsage() 之类的接口,但是绝逼没有那么easy,不过很快掌握了规律。我觉得有必要分享一下我所了解到的知识点,希望能够给各位读者有那么一点抛砖引玉的作用。

我准备通过几篇文章来主要讲述如何使用VSphere WebService SDK 进行对资源信息的监控和告警的采集。对资源监视的监控主要包括:对虚拟机(Virtual Machine)信息的监控(cpu使用情况、磁盘的写入以及读取速度、内存的滞后时间、网络的丢弃的传输和接收的数据报数等待)、对主机(HostSystem)的监控、对集群(Cluster, Compute Resource)信息的监控. 告警也是对这几个主要的对象进行告警采集。

关于软件的安装,譬如vSphere的配置以及vSphere Client的安装就此略过。我这里使用的版本是VMware-vSphere-SDK-5.0.0-429209。

本篇文章主要先阐述一些基本知识。

VMware vSphere支持健壮的、容错的虚拟化应用、网络和存储。vSphere提供许多可选的组件和模块,例如VMware High Availability(HA) 和VMware VMotion。VMware vSphere Web Services SDK提供给Web Services开发者通过编程的方式访问vSphere组件。

vSphere API以无关语言的Web Serivce的形式实现,客户端应用通过远程调用来访问ESX/ESXi, VCenter vSphere systems上的服务和组件。

VMware vSphere客户端程序基于一个异步通讯的分布式架构模型,架构的基础基于server-side managed object, client-side managed object references和data objects.

Managed Object: 在vSphere server(ESX/ESXi 或 vCenter Server system)上,代表着vSphere的服务和组件。服务包括 PropertyCollector, SearchIndex, PerformanceManager和ViewManager。组件包括inventory objects例如VirtualMachine,Datastore和Folder.

Managed Object refereneces:是客户端应用服务器端managed objects.你的客户端应用程序通过使用ManagedObjectReference objects来向服务器发送请求操作。在object的生命周期内ManagedObjectReferences是唯一和持久有效地。当一个存在与清单中由于过期sessions或服务器重启而删除的object的应用会依然存在。假如你删除一个object,例如一个虚拟机,然后又找回它,对它的引用将改变。

Data objects:包含着关于managed objects的信息,你的客户端程序发送data objects和接收data objects与一个vSphere server, 不同的标准和功能object例如VirtualMachineConfigSp和HostCapability.

下图清楚的说明了这三种数据对象及 vSphere Sever 与 client 的关系。


在这三种数据对象中,MO 代表了服务器端的服务或组件,他们都直接或间接继承自 ManagedEntity 抽象类。下面的类图展示了目前 vSphere Infrastructure 中的 7 种最重要的 MO 类型和它们的继承关系,它们代表了 vSphere Infrastructure 中的 7 种组件或者实体。


使用 SDK 开发自己的 vSphere 客户端程序,首要的问题就是如何访问和遍历在 vSphere Inventory 中的对象。下面我们将介绍这方面的内容。

vSphere Inventory 介绍

vSphere inventory 其实就是 vSphere datacenter 及其管理的对象。在 vSphere inventory 中包含了以下三种类型的对象:

在 datacenter 中被管理的系统,比如 Host、VirtualMachine、VirtualApp 等。

具有一定功能的组件,比如 ComputeResource、DataStore,、Network 等。

负责组织归类的组件,它们负责把 datacenter 中的对象按照层级关系组织起来形成了一个树状结构,比如 Folder 和 DataCenter。

ESX/ESXi server 和 vCenter 的 inventory 结构是类似的,只是在 ESX server 中,有些对象的数量有限制,比如在一个 ESX server 的 inventory 中只能有一个 Host 实体。下面两张图分别给出了 vCenter 这 ESX server 的 inventory 的结构。

vCenter Inventory 结构

上面这个关系图很关键,对于系统中关键信息的检索,首先要根据这张图搜寻相关的ManagedObjectReference对象,然后根据此对象的属性树进行遍历。比如搜寻DataCenter对象的相关信息:

[java] view plain copy
  1. private static TraversalSpec getDatacenterTraversalSpec()  
  2. {  
  3.     SelectionSpec sSpec = new SelectionSpec();  
  4.     sSpec.setName("VisitFolders");  
  5.   
  6.     TraversalSpec traversalSpec = new TraversalSpec();  
  7.     traversalSpec.setName("VisitFolders");  
  8.     traversalSpec.setType("Folder");  
  9.     traversalSpec.setPath("childEntity");  
  10.     traversalSpec.setSkip(false);  
  11.     traversalSpec.getSelectSet().add(sSpec);  
  12.     return traversalSpec;  
  13. }  

[java] view plain copy
  1. private static ManagedObjectReference getDatacenterByName(String datacenterName)  
  2. {  
  3.     ManagedObjectReference retVal = null;  
  4.     ManagedObjectReference rootFolder = serviceContent.getRootFolder();  
  5.     try  
  6.     {  
  7.         TraversalSpec tSpec = getDatacenterTraversalSpec();  
  8.         PropertySpec propertySpec = new PropertySpec();  
  9.         propertySpec.setAll(Boolean.FALSE);  
  10.         propertySpec.getPathSet().add("name");  
  11.         propertySpec.setType("Datacenter");  
  12.   
  13.         ObjectSpec objectSpec = new ObjectSpec();  
  14.         objectSpec.setObj(rootFolder);  
  15.         objectSpec.setSkip(Boolean.TRUE);  
  16.         objectSpec.getSelectSet().add(tSpec);  
  17.   
  18.         PropertyFilterSpec propertyFilterSpec = new PropertyFilterSpec();  
  19.         propertyFilterSpec.getPropSet().add(propertySpec);  
  20.         propertyFilterSpec.getObjectSet().add(objectSpec);  
  21.   
  22.         List<PropertyFilterSpec> listfps = new ArrayList<PropertyFilterSpec>(1);  
  23.         listfps.add(propertyFilterSpec);  
  24.         List<ObjectContent> listobcont = retrievePropertiesAllObjects(listfps);  
  25.   
  26.         if (listobcont != null)  
  27.         {  
  28.             for (ObjectContent oc : listobcont)  
  29.             {  
  30.                 ManagedObjectReference mr = oc.getObj();  
  31.                 String dcnm = null;  
  32.                 List<DynamicProperty> dps = oc.getPropSet();  
  33.                 if (dps != null)  
  34.                 {  
  35.                     for (DynamicProperty dp : dps)  
  36.                     {  
  37.                         dcnm = (String) dp.getVal();  
  38.                     }  
  39.                 }  
  40.   
  41.                 if (dcnm != null && dcnm.equals(datacenterName))  
  42.                 {  
  43.                     retVal = mr;  
  44.                     break;  
  45.                 }  
  46.             }  
  47.         }  
  48.     }  
  49.     catch (SOAPFaultException sfe)  
  50.     {  
  51.         printSoapFaultException(sfe);  
  52.     }  
  53.     catch (Exception e)  
  54.     {  
  55.         e.printStackTrace();  
  56.     }  
  57.     return retVal;  
  58. }  

上面的方法getDatacenterTraversalSpec()就是Datacenter的遍历路径代码,然后方法getDatacenterByName(String datacenterName)才能根据获得的遍历路径进行遍历,获取相应的Datacenter的对象。

对于Datacenter的遍历路径代码,比较简单,而对于VirtualMachine或者集群(ComputeResource)之类的遍历路径代码相对复杂,之后再一一罗列。

ESX Server Inventory 结构


想要访问 vCenter 或者 ESX server 中的某个对象或者调用其方法,就必须首先根据这个对象在 inventory 中的位置找个这个对象。从上图可知,ServiceInstance 对象在 inventory 的结构树中处于根位置,因此遍历整个 inventory 或者要查找 inventory 中的某个对象,必须先从 ServiceInstance 开始。ServiceInstance 类中最重要的一个属性(property,可以理解为类的成员变量)是 content,它指向数据类型(Data Object)ServiceContent 的一个实例。ServiceContent 类含有很多该 vSphere 服务实例的重要属性和服务的引用,比如整个 inventory 的 root folder,session manager,property collector(用于查找和遍历对象),以及 EventManager, TaskManager 等。下面的类图展示了 ServiceInstance 和 ServiceContent 的部分属性。

ServiceInstance 和 ServiceContent

以上资料在网上或者vSphere sdk自带的API或者自带的用例demo中可以找到相关的信息。本人只是挑一些重要概念陈述,接下去才主要讲解如何通过编码实现实时监控私有云的状态,譬如虚拟机cpu使用情况等性能指标。

下面罗列一些主要的关键代码(可以在vSphere sdk自带的demo中找到相关代码),包括认证、连接、断开之类的操作。

[java] view plain copy
  1. public class MoniterWsInterface  
  2. {  
  3.     private static String url;  
  4.     private static String userName;  
  5.     private static String password;  
  6.   
  7.     private static final ManagedObjectReference SVC_INST_REF = new ManagedObjectReference();  
  8.     private static VimService vimService;  
  9.     private static VimPortType vimPort;  
  10.   
  11.     private static ServiceContent serviceContent;  
  12.     private static final String SVC_INST_NAME = "ServiceInstance";  
  13.     private static Boolean isConnected = false;  
  14.     private static ManagedObjectReference perfManager;  
  15.     private static ManagedObjectReference propCollectorRef;  
  16.   
  17.     public MoniterWsInterface(String puserName, String ppassWord, String purl)  
  18.     {  
  19.         url = purl;  
  20.         userName = puserName;  
  21.         password = ppassWord;  
  22.     }  
  23.   
  24.     private static class TrustAllTrustManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager  
  25.     {  
  26.         public java.security.cert.X509Certificate[] getAcceptedIssuers()  
  27.         {  
  28.             return null;  
  29.         }  
  30.   
  31.         public boolean isServerTrusted(java.security.cert.X509Certificate[] certs)  
  32.         {  
  33.             return true;  
  34.         }  
  35.   
  36.         public boolean isClientTrusted(java.security.cert.X509Certificate[] certs)  
  37.         {  
  38.             return true;  
  39.         }  
  40.   
  41.         public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException  
  42.         {  
  43.             return;  
  44.         }  
  45.   
  46.         public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException  
  47.         {  
  48.             return;  
  49.         }  
  50.     }  
  51.   
  52.     private static void trustAllHttpsCertificates() throws Exception  
  53.     {  
  54.         javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];  
  55.         javax.net.ssl.TrustManager tm = new TrustAllTrustManager();  
  56.         trustAllCerts[0] = tm;  
  57.         javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");  
  58.         javax.net.ssl.SSLSessionContext sslsc = sc.getServerSessionContext();  
  59.         sslsc.setSessionTimeout(0);  
  60.         sc.init(null, trustAllCerts, null);  
  61.         javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());  
  62.     }  
  63.   
  64.     public static void connect() throws Exception  
  65.     {  
  66.         HostnameVerifier hv = new HostnameVerifier()  
  67.         {  
  68.             public boolean verify(String urlHostName, SSLSession session)  
  69.             {  
  70.                 return true;  
  71.             }  
  72.         };  
  73.         trustAllHttpsCertificates();  
  74.   
  75.         HttpsURLConnection.setDefaultHostnameVerifier(hv);  
  76.   
  77.         SVC_INST_REF.setType(SVC_INST_NAME);  
  78.         SVC_INST_REF.setValue(SVC_INST_NAME);  
  79.   
  80.         vimService = new VimService();  
  81.         vimPort = vimService.getVimPort();  
  82.         Map<String, Object> ctxt = ((BindingProvider) vimPort).getRequestContext();  
  83.   
  84.         ctxt.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);  
  85.         ctxt.put(BindingProvider.SESSION_MAINTAIN_PROPERTY, true);  
  86.   
  87.         serviceContent = vimPort.retrieveServiceContent(SVC_INST_REF);  
  88.         vimPort.login(serviceContent.getSessionManager(), userName, password, null);  
  89.         isConnected = true;  
  90.   
  91.         perfManager = serviceContent.getPerfManager();  
  92.         propCollectorRef = serviceContent.getPropertyCollector();  
  93.     }  
  94.   
  95.     public static void disconnect() throws Exception  
  96.     {  
  97.         if (isConnected)  
  98.         {  
  99.             vimPort.logout(serviceContent.getSessionManager());  
  100.         }  
  101.         isConnected = false;  
  102.     }  
  103.   
  104.     private static void printSoapFaultException(SOAPFaultException sfe)  
  105.     {  
  106.         System.out.println("Soap fault: ");  
  107.         if (sfe.getFault().hasDetail())  
  108.         {  
  109.             System.out.println(sfe.getFault().getDetail().getFirstChild().getLocalName());  
  110.         }  
  111.         if (sfe.getFault().getFaultString() != null)  
  112.         {  
  113.             System.out.println("Message: " + sfe.getFault().getFaultString());  
  114.         }  
  115.     }  
  116.     public static void main(String[] args)  
  117.     {  
  118.         new MoniterWsInterface("xxx""xxx""xxx");  
  119.         try  
  120.         {  
  121.             connect();  
  122.         }  
  123.         catch (SOAPFaultException sfe)  
  124.         {  
  125.             printSoapFaultException(sfe);  
  126.         }  
  127.         catch (Exception e)  
  128.         {  
  129.             e.printStackTrace();  
  130.         }  
  131.         finally  
  132.         {  
  133.             try  
  134.             {  
  135.                 disconnect();  
  136.             }  
  137.             catch (SOAPFaultException sfe)  
  138.             {  
  139.                 printSoapFaultException(sfe);  
  140.             }  
  141.             catch (Exception e)  
  142.             {  
  143.                 e.printStackTrace();  
  144.             }  
  145.         }  
  146.     }  
  147. }  
这样就可以通过相关连接信息(username,password,url)进行相关连接。

由于篇幅原因,接下来的内容在之后的文章中一一呈现。

补充:retrievePropertiesAllObjects的代码:

[java] view plain copy
  1. private static List<ObjectContent> retrievePropertiesAllObjects(List<PropertyFilterSpec> listpfs) throws Exception  
  2. {  
  3.     RetrieveOptions propObjectRetrieveOpts = new RetrieveOptions();  
  4.     List<ObjectContent> listobjcontent = new ArrayList<ObjectContent>();  
  5.   
  6.     try  
  7.     {  
  8.         RetrieveResult rslts = vimPort.retrievePropertiesEx(propCollectorRef, listpfs, propObjectRetrieveOpts);  
  9.         if (rslts != null && rslts.getObjects() != null && !rslts.getObjects().isEmpty())  
  10.         {  
  11.             listobjcontent.addAll(rslts.getObjects());  
  12.         }  
  13.         String token = null;  
  14.         if (rslts != null && rslts.getToken() != null)  
  15.         {  
  16.             token = rslts.getToken();  
  17.         }  
  18.         while (token != null && !token.isEmpty())  
  19.         {  
  20.             rslts = vimPort.continueRetrievePropertiesEx(propCollectorRef, token);  
  21.             token = null;  
  22.             if (rslts != null)  
  23.             {  
  24.                 token = rslts.getToken();  
  25.                 if (rslts.getObjects() != null && !rslts.getObjects().isEmpty())  
  26.                 {  
  27.                     listobjcontent.addAll(rslts.getObjects());  
  28.                 }  
  29.             }  
  30.         }  
  31.     }  
  32.     catch (SOAPFaultException sfe)  
  33.     {  
  34.         printSoapFaultException(sfe);  
  35.     }  
  36.     catch (Exception e)  
  37.     {  
  38.         e.printStackTrace();  
  39.     }  
  40.   
  41.     return listobjcontent;  
  42. }  
1 0