刚开始这方面开发的时候,不知道如何下手,能够查到的资料特别少,而且看到很多网友和我一样也在找这方面的资料。接下来的一段时间我就结合自己所参与的项目,完成关于Vmware Vsphere WebService SDK开发的一系列教程(java),分享自己在Vmware开发过程中学习到的知识,希望能和大家一起进步。
今天先和大家学习下一些基本知识,我参考官方6.0英文文档,SDK版本:VMware-vSphere-SDK-6.0.0-2561048。
Managed Object: 代表服务端对象,在vSphere server(ESX/ESXi 或 vCenter Server system)上,代表着vSphere的服务和组件,都直接或间接继承自 ManagedEntity 抽象类。
Managed Object refereneces:代表客户端对服务端对象的引用,客户端应用程序通过使用ManagedObjectReference objects来向服务器发送请求操作。
Data objects:包含着关于managed objects的信息,你的客户端通过发送data objects和接收data objects与服务端进行通信(通过键值对的形式)。
图示为三者之间的关系:
接下来贴上认证、连接、断开vcenter server的代码(java):这个代码在官方的例子中也有,直接拿过来用替换掉里面的url、username、password即可,代码可以直接运行。
1 import java.util.ArrayList; 2 import java.util.List; 3 import java.util.Map; 4 5 import javax.net.ssl.HostnameVerifier; 6 import javax.net.ssl.HttpsURLConnection; 7 import javax.net.ssl.SSLSession; 8 import javax.xml.ws.BindingProvider; 9 import javax.xml.ws.soap.SOAPFaultException; 10 11 import com.vmware.vim25.ManagedObjectReference; 12 import com.vmware.vim25.ObjectContent; 13 import com.vmware.vim25.PropertyFilterSpec; 14 import com.vmware.vim25.RetrieveOptions; 15 import com.vmware.vim25.RetrieveResult; 16 import com.vmware.vim25.ServiceContent; 17 import com.vmware.vim25.VimPortType; 18 import com.vmware.vim25.VimService; 19 20 /** 21 * @author Di 22 * @功能描述 服务器的连接、认证、断开 23 * @date 创建时间:2016年12月8日 下午3:37:18 24 * @version 1.0 25 */ 26 public class MoniterWsInterface 27 { 28 private static String url = ""; 29 private static String userName = ""; 30 private static String password = ""; 31 32 private static final ManagedObjectReference SVC_INST_REF = new ManagedObjectReference(); 33 public static VimService vimService; 34 public static VimPortType vimPort; 35 36 public static ServiceContent serviceContent; 37 private static final String SVC_INST_NAME = "ServiceInstance"; 38 private static Boolean isConnected = false; 39 public static ManagedObjectReference perfManager; 40 public static ManagedObjectReference propCollectorRef; 41 42 private static class TrustAllTrustManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager 43 { 44 public java.security.cert.X509Certificate[] getAcceptedIssuers() 45 { 46 return null; 47 } 48 49 public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) 50 { 51 return true; 52 } 53 54 public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) 55 { 56 return true; 57 } 58 59 public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException 60 { 61 return; 62 } 63 64 public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException 65 { 66 return; 67 } 68 } 69 70 private static void trustAllHttpsCertificates() throws Exception 71 { 72 javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; 73 javax.net.ssl.TrustManager tm = new TrustAllTrustManager(); 74 trustAllCerts[0] = tm; 75 javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL"); 76 javax.net.ssl.SSLSessionContext sslsc = sc.getServerSessionContext(); 77 sslsc.setSessionTimeout(0); 78 sc.init(null, trustAllCerts, null); 79 javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 80 } 81 82 /** 83 * @功能描述 连接认证 84 */ 85 public static void connect() throws Exception 86 { 87 HostnameVerifier hv = new HostnameVerifier() 88 { 89 public boolean verify(String urlHostName, SSLSession session) 90 { 91 return true; 92 } 93 }; 94 trustAllHttpsCertificates(); 95 96 HttpsURLConnection.setDefaultHostnameVerifier(hv); 97 98 SVC_INST_REF.setType(SVC_INST_NAME); 99 SVC_INST_REF.setValue(SVC_INST_NAME); 100 101 vimService = new VimService(); 102 vimPort = vimService.getVimPort(); 103 Map<String, Object> ctxt = ((BindingProvider) vimPort).getRequestContext(); 104 105 ctxt.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url); 106 ctxt.put(BindingProvider.SESSION_MAINTAIN_PROPERTY, true); 107 108 serviceContent = vimPort.retrieveServiceContent(SVC_INST_REF); 109 vimPort.login(serviceContent.getSessionManager(), userName, password, null); 110 isConnected = true; 111 112 perfManager = serviceContent.getPerfManager(); 113 propCollectorRef = serviceContent.getPropertyCollector(); 114 115 System.out.println(serviceContent.getAbout().getFullName()); 116 System.out.println("Server type is " + serviceContent.getAbout().getApiType()); 117 } 118 119 /** 120 * @功能描述 断开连接 121 * @return 122 * @throws Exception 123 */ 124 public static void disconnect() throws Exception 125 { 126 if (isConnected) 127 { 128 vimPort.logout(serviceContent.getSessionManager()); 129 } 130 isConnected = false; 131 } 132 133 /** 134 * @功能描述 打印错误信息 135 * @param 136 * @param sfe 137 */ 138 public static void printSoapFaultException(SOAPFaultException sfe) 139 { 140 System.out.println("Soap fault: "); 141 if (sfe.getFault().hasDetail()) 142 { 143 System.out.println(sfe.getFault().getDetail().getFirstChild().getLocalName()); 144 } 145 if (sfe.getFault().getFaultString() != null) 146 { 147 System.out.println("Message: " + sfe.getFault().getFaultString()); 148 } 149 } 150 151 /** 152 * @功能描述 根据属性检索要查询的对象信息 153 * @param listpfs 属性过滤器集合 154 * @throws Exception 155 */ 156 public static List<ObjectContent> retrievePropertiesAllObjects(List<PropertyFilterSpec> listpfs) throws Exception 157 { 158 RetrieveOptions propObjectRetrieveOpts = new RetrieveOptions(); 159 List<ObjectContent> listobjcontent = new ArrayList<ObjectContent>(); 160 try 161 { 162 RetrieveResult rslts = vimPort.retrievePropertiesEx(propCollectorRef, listpfs, propObjectRetrieveOpts); 163 if (rslts != null && rslts.getObjects() != null && !rslts.getObjects().isEmpty()) 164 { 165 listobjcontent.addAll(rslts.getObjects()); 166 } 167 String token = null; 168 if (rslts != null && rslts.getToken() != null) 169 { 170 token = rslts.getToken(); 171 } 172 while (token != null && !token.isEmpty()) 173 { 174 rslts = vimPort.continueRetrievePropertiesEx(propCollectorRef, token); 175 token = null; 176 if (rslts != null) 177 { 178 token = rslts.getToken(); 179 if (rslts.getObjects() != null && !rslts.getObjects().isEmpty()) 180 { 181 listobjcontent.addAll(rslts.getObjects()); 182 } 183 } 184 } 185 } 186 catch (SOAPFaultException sfe) 187 { 188 printSoapFaultException(sfe); 189 } 190 catch (Exception e) 191 { 192 e.printStackTrace(); 193 } 194 195 return listobjcontent; 196 } 197 198 /** 199 * @see main测试方法 200 * */ 201 public static void main(String[] args) 202 { 203 new MoniterWsInterface(); 204 try 205 { 206 connect(); 207 } 208 catch (SOAPFaultException sfe) 209 { 210 printSoapFaultException(sfe); 211 } 212 catch (Exception e) 213 { 214 e.printStackTrace(); 215 } 216 finally 217 { 218 try 219 { 220 disconnect(); 221 } 222 catch (SOAPFaultException sfe) 223 { 224 printSoapFaultException(sfe); 225 } 226 catch (Exception e) 227 { 228 e.printStackTrace(); 229 } 230 } 231 } 232 }
现在我们对Vcenter中涉及的三种数据类型有了一定的认识,接下来学习重要的清单遍历知识。
清单层次和servicetInstance:
Serviceinstance:Serviceinstance是清单根对象,从这里开始访问清单的各个层次,通常一个serviceinstance会绑定一个session,当开启session时,vsphere会创建一个具有rootFolder,和四个不同类型Folder的serviceInstance。
rootFolder:清单遍历根目录。
Datacenter:rootFolder下就是数据中心,数据中心可以创建多个,一个session会自带一个。
hostFolder(左一):包含ComputeResource(计算资源)的目录,ComputeResource下还有HostSystem(主机)、ResourcePool(资源池)对象,如果想获取计算资源、主机、资源池、集群的对象及其信息,就需要通过此条路径遍历获取。
vmFolder(左二):包含VirtualMachine(虚拟机)、VirtualApp(虚拟应用),如果想获取虚拟机对象或虚拟机相关信息,就需要通过此遍历层次遍历获取。
networkFolder(右二):包含Network(网络),此条遍历路径便是获取Network的。
datastoreFolder(右一):包含Datastore(数据存储),通过此遍历路径获取和数据存储相关的所有信息。
图一
访问具体清单元素的遍历路径:
从清单的根元素ServiceInstance开始,通过带有(Property collector)属性收集器的TraversalSpec和对象的属性确定对象在清单中的位置。
ServiceInstance具有content的属性:content属性是ServiceContent对象,serviceContent中包含很多重要的属性和服务的引用。
ServiceContent具有rootFolder属性:属性是rootFolder。
rootFolder有childEntity属性:属性指向的对象便是Datacenter(数据中心)。
Datacenter用于四个不同的Folder属性:分别指向四个不同的Folder对象,hostFolder、vmFolder、networkFolder、datastoreFolder(参照图一)。
每一个Folder对应childEntity属性:hostFolder对应ComputeResource等,vmFolder对象VirtualMachine等,networkFolder对应NetWork,datastoreFolder对应DataStore等。(可参考图一)
前面讲了这么多清单遍历的知识,接下来就和大家演示下如何获取Datacenter对象及其属性,代码可以直接运行。
1 import java.util.ArrayList; 2 import java.util.List; 3 4 import javax.xml.ws.soap.SOAPFaultException; 5 6 import com.vmware.vim25.DynamicProperty; 7 import com.vmware.vim25.ManagedObjectReference; 8 import com.vmware.vim25.ObjectContent; 9 import com.vmware.vim25.ObjectSpec; 10 import com.vmware.vim25.PropertyFilterSpec; 11 import com.vmware.vim25.PropertySpec; 12 import com.vmware.vim25.SelectionSpec; 13 import com.vmware.vim25.TraversalSpec; 14 15 /** 16 * @author Di 17 * @see 获取数据中心对象引用及name属性 18 * @date 创建时间:2016年12月8日 下午4:01:33 19 * @version 1.0 20 */ 21 public class GetDataCenter { 22 23 /** 24 * @see 获取遍历数据中心的TraversalSpec 25 * @explain:清单遍历一定要结合清单遍历结构图。 26 * @return TraversalSpec:清单遍历对象,明确属性收集的对象类型,同事提供对象遍历的路径。 27 * */ 28 public static TraversalSpec getDatacenterTraversalSpec() 29 { 30 //SelectionSpec是TraversalSpec的一个引用。 31 SelectionSpec sSpec = new SelectionSpec(); 32 sSpec.setName("VisitFolders"); 33 34 TraversalSpec traversalSpec = new TraversalSpec(); 35 //给traversalSpec设置名称 36 traversalSpec.setName("VisitFolders"); 37 //从rootFolder开始遍历,rootFolder类型是Folder 38 traversalSpec.setType("Folder"); 39 //rootFolder拥有childEntity属性,清单结构图中指向的便是Datacenter 40 traversalSpec.setPath("childEntity"); 41 //false表示不对其本身进行收集,只对其下对象进行收集 42 traversalSpec.setSkip(false); 43 //将sSpec添加到SelectionSpec集合中 44 traversalSpec.getSelectSet().add(sSpec); 45 return traversalSpec; 46 } 47 48 /** 49 * @see 获取出所有的数据中心 50 * @return retVal:数据中心对象引用list。 51 * */ 52 public static List<ManagedObjectReference> getAllDatacenter() 53 { 54 List<ManagedObjectReference> retVal = new ArrayList<ManagedObjectReference>(); 55 //获取根目录对象引用 56 ManagedObjectReference rootFolder = MoniterWsInterface.serviceContent.getRootFolder(); 57 try 58 { 59 TraversalSpec tSpec = getDatacenterTraversalSpec(); 60 61 /** 62 * ObjectSpec:定义对象详述,明确清单导航起始点。 63 * obj:定义遍历起始对象为根目录rootFolder 64 * true:表示只收集Datacenter的数据,不收集containerView的数据。 65 * */ 66 ObjectSpec objectSpec = new ObjectSpec(); 67 objectSpec.setObj(rootFolder); 68 objectSpec.setSkip(Boolean.TRUE); 69 70 /** 添加 tSpec到 ObjectSpec.selectSet队列中 */ 71 objectSpec.getSelectSet().add(tSpec); 72 73 /** 74 * PropertySpec:定义一个属性收集器详述,明确收集的具体对象(Datacenter)和属性(Datacenter中的name,可以为多个) 75 * Type:具体的对象类型为Datacenter 76 * pathset:明确对象Datacenter中的属性,可以为多个。 77 * */ 78 PropertySpec propertySpec = new PropertySpec(); 79 propertySpec.setAll(Boolean.FALSE); 80 propertySpec.getPathSet().add("name"); 81 propertySpec.setType("Datacenter"); 82 83 /** 84 * PropertyFilterSpec:定义一个属性过滤器详述,添加对象详述和属性收集器详述到过率中 85 * */ 86 PropertyFilterSpec propertyFilterSpec = new PropertyFilterSpec(); 87 propertyFilterSpec.getPropSet().add(propertySpec); 88 propertyFilterSpec.getObjectSet().add(objectSpec); 89 90 /** 添加属性过滤器详述到属性过滤器集合中 */ 91 List<PropertyFilterSpec> listfps = new ArrayList<PropertyFilterSpec>(1); 92 listfps.add(propertyFilterSpec); 93 94 /** 调用方法获取ObjectContent对象集合 */ 95 List<ObjectContent> listobcont = MoniterWsInterface.retrievePropertiesAllObjects(listfps); 96 97 if (listobcont != null) 98 { 99 for (ObjectContent oc : listobcont) 100 { 101 //根据object对象获得MOR对象 102 ManagedObjectReference mr = oc.getObj(); 103 104 String dcnm = null; 105 //获取属性集合(此处只有一个name属性) 106 List<DynamicProperty> dps = oc.getPropSet(); 107 if (dps != null) 108 { 109 for (DynamicProperty dp : dps) 110 { 111 //获取到具体的数据中心(Datacenter)的名称 112 dcnm = (String) dp.getVal(); 113 //System.out.println("数据中心名称"+dcnm); 114 retVal.add(mr); 115 } 116 } 117 } 118 } 119 } 120 catch (SOAPFaultException sfe) 121 { 122 MoniterWsInterface.printSoapFaultException(sfe); 123 } 124 catch (Exception e) 125 { 126 e.printStackTrace(); 127 } 128 return retVal; 129 } 130 131 /** 132 * @see 获取出所有的数据中心,和上面方法一样,只是最后返回值取得是Datacenter的属性name的值,而非Datacenter的对象引用。 133 * @return retVal:数据中心名称list。 134 * */ 135 public static List<String> getDatacenterName() 136 { 137 List<String> retVal = new ArrayList<String>(); 138 ManagedObjectReference rootFolder = MoniterWsInterface.serviceContent.getRootFolder(); 139 try 140 { 141 TraversalSpec tSpec = getDatacenterTraversalSpec(); 142 143 ObjectSpec objectSpec = new ObjectSpec(); 144 objectSpec.setObj(rootFolder); 145 objectSpec.setSkip(Boolean.TRUE); 146 objectSpec.getSelectSet().add(tSpec); 147 148 PropertySpec propertySpec = new PropertySpec(); 149 propertySpec.setAll(Boolean.FALSE); 150 propertySpec.getPathSet().add("name"); 151 propertySpec.setType("Datacenter"); 152 153 //添加对象和属性声明到 PropertyFilterSpec。 154 PropertyFilterSpec propertyFilterSpec = new PropertyFilterSpec(); 155 propertyFilterSpec.getPropSet().add(propertySpec); 156 propertyFilterSpec.getObjectSet().add(objectSpec); 157 158 List<PropertyFilterSpec> listfps = new ArrayList<PropertyFilterSpec>(1); 159 listfps.add(propertyFilterSpec); 160 161 List<ObjectContent> listobcont = MoniterWsInterface.retrievePropertiesAllObjects(listfps); 162 163 if (listobcont != null) 164 { 165 for (ObjectContent oc : listobcont) 166 { 167 //根据object对象获得MOR对象 168 ManagedObjectReference mr = oc.getObj(); 169 170 String dcnm = null; 171 List<DynamicProperty> dps = oc.getPropSet(); 172 if (dps != null) 173 { 174 for (DynamicProperty dp : dps) 175 { 176 dcnm = (String) dp.getVal(); 177 retVal.add(dcnm); 178 } 179 } 180 } 181 } 182 } 183 catch (SOAPFaultException sfe) 184 { 185 MoniterWsInterface.printSoapFaultException(sfe); 186 } 187 catch (Exception e) 188 { 189 e.printStackTrace(); 190 } 191 return retVal; 192 } 193 194 /** 195 * @see main测试方法 196 * */ 197 public static void main(String[] args) throws Exception { 198 MoniterWsInterface moniterWsInterface = new MoniterWsInterface(); 199 moniterWsInterface.connect(); 200 201 /* List<ManagedObjectReference> allDatacenter = getAllDatacenter(); 202 for (ManagedObjectReference dataCenter : allDatacenter) { 203 System.out.println(dataCenter.getType()); 204 }*/ 205 List<String> datacenterName = getDatacenterName(); 206 for (String name : datacenterName) { 207 System.out.println(name); 208 } 209 moniterWsInterface.disconnect(); 210 } 211 }
今天的入门知识就先讲这么多,新手一定要先学习下文档掌握基本的知识,然后结合代码练手,这样的可以更快的掌握套路。
关于主机、虚拟机、存储、集群等等其他的操作,我会在之后的文章为大家呈现,敬请期待。如果对哪块资源的操作需求特别紧急,可以给我评论留言。