剛開始這方面開發的時候,不知道如何下手,能夠查到的資料特別少,而且看到很多網友和我一樣也在找這方面的資料。接下來的一段時間我就結合自己所參與的項目,完成關於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即可,代碼可以直接運行。
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.soap.SOAPFaultException;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.ObjectContent;
import com.vmware.vim25.PropertyFilterSpec;
import com.vmware.vim25.RetrieveOptions;
import com.vmware.vim25.RetrieveResult;
import com.vmware.vim25.ServiceContent;
import com.vmware.vim25.VimPortType;
import com.vmware.vim25.VimService;
/**
* @author Di
* @功能描述 服務器的連接、認證、斷開
* @date 創建時間:2016年12月8日 下午3:37:18
* @version 1.0
*/
public class MoniterWsInterface
{
private static String url = "";
private static String userName = "";
private static String password = "";
private static final ManagedObjectReference SVC_INST_REF = new ManagedObjectReference();
public static VimService vimService;
public static VimPortType vimPort;
public static ServiceContent serviceContent;
private static final String SVC_INST_NAME = "ServiceInstance";
private static Boolean isConnected = false;
public static ManagedObjectReference perfManager;
public static ManagedObjectReference propCollectorRef;
private static class TrustAllTrustManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager
{
public java.security.cert.X509Certificate[] getAcceptedIssuers()
{
return null;
}
public boolean isServerTrusted(java.security.cert.X509Certificate[] certs)
{
return true;
}
public boolean isClientTrusted(java.security.cert.X509Certificate[] certs)
{
return true;
}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException
{
return;
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException
{
return;
}
}
private static void trustAllHttpsCertificates() throws Exception
{
javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
javax.net.ssl.TrustManager tm = new TrustAllTrustManager();
trustAllCerts[0] = tm;
javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
javax.net.ssl.SSLSessionContext sslsc = sc.getServerSessionContext();
sslsc.setSessionTimeout(0);
sc.init(null, trustAllCerts, null);
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
/**
* @功能描述 連接認證
*/
public static void connect() throws Exception
{
HostnameVerifier hv = new HostnameVerifier()
{
public boolean verify(String urlHostName, SSLSession session)
{
return true;
}
};
trustAllHttpsCertificates();
HttpsURLConnection.setDefaultHostnameVerifier(hv);
SVC_INST_REF.setType(SVC_INST_NAME);
SVC_INST_REF.setValue(SVC_INST_NAME);
vimService = new VimService();
vimPort = vimService.getVimPort();
Map<String, Object> ctxt = ((BindingProvider) vimPort).getRequestContext();
ctxt.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
ctxt.put(BindingProvider.SESSION_MAINTAIN_PROPERTY, true);
serviceContent = vimPort.retrieveServiceContent(SVC_INST_REF);
vimPort.login(serviceContent.getSessionManager(), userName, password, null);
isConnected = true;
perfManager = serviceContent.getPerfManager();
propCollectorRef = serviceContent.getPropertyCollector();
System.out.println(serviceContent.getAbout().getFullName());
System.out.println("Server type is " + serviceContent.getAbout().getApiType());
}
/**
* @功能描述 斷開連接
* @return
* @throws Exception
*/
public static void disconnect() throws Exception
{
if (isConnected)
{
vimPort.logout(serviceContent.getSessionManager());
}
isConnected = false;
}
/**
* @功能描述 打印錯誤信息
* @param
* @param sfe
*/
public static void printSoapFaultException(SOAPFaultException sfe)
{
System.out.println("Soap fault: ");
if (sfe.getFault().hasDetail())
{
System.out.println(sfe.getFault().getDetail().getFirstChild().getLocalName());
}
if (sfe.getFault().getFaultString() != null)
{
System.out.println("Message: " + sfe.getFault().getFaultString());
}
}
/**
* @功能描述 根據屬性檢索要查詢的對象信息
* @param listpfs 屬性過濾器集合
* @throws Exception
*/
public static List<ObjectContent> retrievePropertiesAllObjects(List<PropertyFilterSpec> listpfs) throws Exception
{
RetrieveOptions propObjectRetrieveOpts = new RetrieveOptions();
List<ObjectContent> listobjcontent = new ArrayList<ObjectContent>();
try
{
RetrieveResult rslts = vimPort.retrievePropertiesEx(propCollectorRef, 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 = vimPort.continueRetrievePropertiesEx(propCollectorRef, token);
token = null;
if (rslts != null)
{
token = rslts.getToken();
if (rslts.getObjects() != null && !rslts.getObjects().isEmpty())
{
listobjcontent.addAll(rslts.getObjects());
}
}
}
}
catch (SOAPFaultException sfe)
{
printSoapFaultException(sfe);
}
catch (Exception e)
{
e.printStackTrace();
}
return listobjcontent;
}
/**
* @see main測試方法
* */
public static void main(String[] args)
{
new MoniterWsInterface();
try
{
connect();
}
catch (SOAPFaultException sfe)
{
printSoapFaultException(sfe);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
try
{
disconnect();
}
catch (SOAPFaultException sfe)
{
printSoapFaultException(sfe);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
現在我們對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對象及其屬性,代碼可以直接運行。
import java.util.ArrayList;
import java.util.List;
import javax.xml.ws.soap.SOAPFaultException;
import com.vmware.vim25.DynamicProperty;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.ObjectContent;
import com.vmware.vim25.ObjectSpec;
import com.vmware.vim25.PropertyFilterSpec;
import com.vmware.vim25.PropertySpec;
import com.vmware.vim25.SelectionSpec;
import com.vmware.vim25.TraversalSpec;
/**
* @author Di
* @see 獲取數據中心對象引用及name屬性
* @date 創建時間:2016年12月8日 下午4:01:33
* @version 1.0
*/
public class GetDataCenter {
/**
* @see 獲取遍歷數據中心的TraversalSpec
* @explain:清單遍歷一定要結合清單遍歷結構圖。
* @return TraversalSpec:清單遍歷對象,明確屬性收集的對象類型,同事提供對象遍歷的路徑。
* */
public static 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;
}
/**
* @see 獲取出所有的數據中心
* @return retVal:數據中心對象引用list。
* */
public static List<ManagedObjectReference> getAllDatacenter()
{
List<ManagedObjectReference> retVal = new ArrayList<ManagedObjectReference>();
//獲取根目錄對象引用
ManagedObjectReference rootFolder = MoniterWsInterface.serviceContent.getRootFolder();
try
{
TraversalSpec tSpec = getDatacenterTraversalSpec();
/**
* ObjectSpec:定義對象詳述,明確清單導航起始點。
* obj:定義遍歷起始對象爲根目錄rootFolder
* true:表示只收集Datacenter的數據,不收集containerView的數據。
* */
ObjectSpec objectSpec = new ObjectSpec();
objectSpec.setObj(rootFolder);
objectSpec.setSkip(Boolean.TRUE);
/** 添加 tSpec到 ObjectSpec.selectSet隊列中 */
objectSpec.getSelectSet().add(tSpec);
/**
* PropertySpec:定義一個屬性收集器詳述,明確收集的具體對象(Datacenter)和屬性(Datacenter中的name,可以爲多個)
* Type:具體的對象類型爲Datacenter
* pathset:明確對象Datacenter中的屬性,可以爲多個。
* */
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);
/** 調用方法獲取ObjectContent對象集合 */
List<ObjectContent> listobcont = MoniterWsInterface.retrievePropertiesAllObjects(listfps);
if (listobcont != null)
{
for (ObjectContent oc : listobcont)
{
//根據object對象獲得MOR對象
ManagedObjectReference mr = oc.getObj();
String dcnm = null;
//獲取屬性集合(此處只有一個name屬性)
List<DynamicProperty> dps = oc.getPropSet();
if (dps != null)
{
for (DynamicProperty dp : dps)
{
//獲取到具體的數據中心(Datacenter)的名稱
dcnm = (String) dp.getVal();
//System.out.println("數據中心名稱"+dcnm);
retVal.add(mr);
}
}
}
}
}
catch (SOAPFaultException sfe)
{
MoniterWsInterface.printSoapFaultException(sfe);
}
catch (Exception e)
{
e.printStackTrace();
}
return retVal;
}
/**
* @see 獲取出所有的數據中心,和上面方法一樣,只是最後返回值取得是Datacenter的屬性name的值,而非Datacenter的對象引用。
* @return retVal:數據中心名稱list。
* */
public static List<String> getDatacenterName()
{
List<String> retVal = new ArrayList<String>();
ManagedObjectReference rootFolder = MoniterWsInterface.serviceContent.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 = MoniterWsInterface.retrievePropertiesAllObjects(listfps);
if (listobcont != null)
{
for (ObjectContent oc : listobcont)
{
//根據object對象獲得MOR對象
ManagedObjectReference mr = oc.getObj();
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)
{
MoniterWsInterface.printSoapFaultException(sfe);
}
catch (Exception e)
{
e.printStackTrace();
}
return retVal;
}
/**
* @see main測試方法
* */
public static void main(String[] args) throws Exception {
MoniterWsInterface moniterWsInterface = new MoniterWsInterface();
moniterWsInterface.connect();
/* List<ManagedObjectReference> allDatacenter = getAllDatacenter();
for (ManagedObjectReference dataCenter : allDatacenter) {
System.out.println(dataCenter.getType());
}*/
List<String> datacenterName = getDatacenterName();
for (String name : datacenterName) {
System.out.println(name);
}
moniterWsInterface.disconnect();
}
}