免费版的VMWare ESXi 从v3.5 u3开始,禁止了SDK和vCli的“写”调用。

也就是说,从ESXi 3.5u3开始,我们不能用SDK或者vCLI命令行,控制免费版ESXi上运行的虚拟机了,不能对其进行重起,关机等任何“写”操作。
后来无意中在网上发现了一个叫esxi-control.pl的脚本,可以用来控制免费版ESXi上的虚拟机,地址如下

脚 本是用Perl写的,通过模拟vSphere Client发出的SOAP消息来控制ESXi.但是这个Perl脚本 仍然需要调用Perl-vCLI去获得虚拟机的id信息。我想既然能够模拟SOAP的控制消息,那也一定能模拟读取虚拟机信息的消息啊,但是平时用 Perl很少,所以干脆就用JAVA写了一个实现。

先说说程序的原理,
程序调用Apache的httpclient来完成SOAP消息的发送与接受。

第一步,发送下列SOAP消息来建立连接与身份认证, $ USERNAME$和 $ PASSWORD$为ESXi主机的登陆用户名和密码
  1. < soap:Envelope xmlns:xsd= "http://www.w3.org/2001/XMLSchema" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:soap= "http://schemas.xmlsoap.org/soap/envelope/" >
  2.     < soap:Body>
  3.         < Login xmlns= "urn:internalvim25" >
  4.             < _this xsi:type= "SessionManager" type= "SessionManager" serverGuid= "" > ha-sessionmgr< / _this>
  5.             < userName> $ USERNAME$< / userName>
  6.             < password> $ PASSWORD$< / password>
  7.             < locale> en_US< / locale>
  8.         < / Login>
  9.     < / soap:Body>
  10. < / soap:Envelope>
第二步,获取当前已连接主机上的虚拟机列表,SOAP消息如下
  1. < soapenv:Envelope xmlns:soapenv= "http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd= "http://www.w3.org/2001/XMLSchema" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" >
  2.         < soapenv:Body>
  3.                 < RetrieveProperties xmlns= "urn:vim25" >
  4.                         < _this type= "PropertyCollector" > ha-property-collector< / _this>
  5.                         < specSet>
  6.                                 < propSet>
  7.                                         < type> HostSystem< / type>
  8.                                         < all> 0< / all>
  9.                                         < pathSet> vm< / pathSet>
  10.                                 < / propSet>
  11.                                 < objectSet>
  12.                                         < obj type= "HostSystem" > ha-host< / obj>
  13.                                 < / objectSet>
  14.                         < / specSet>
  15.                 < / RetrieveProperties>
  16.         < / soapenv:Body>
  17. < / soapenv:Envelope>
第 三步,第二步返回的消息里面只有虚拟机的ID,但是用户一般是不知道虚拟机的ID是干啥的,所以,我们需要虚拟机的名称等其它信息,所以发送下面的消息用 来获取虚拟机其它的信息,包括虚拟机的名称,虚拟机的网络名称,IP地址,开关机状态以及VMWareTool的运行情况。
其中的$VMID$就是要获取具体信息的虚拟机ID
可以有多个 <objectSet>,用来一次性获取多台虚拟机的信息
  1. < soapenv:Envelope xmlns:soapenv= "http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd= "http://www.w3.org/2001/XMLSchema" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" >
  2.     < soapenv:Body>
  3.             < RetrieveProperties xmlns= "urn:vim25" >
  4.                 < _this type= "PropertyCollector" > ha-property-collector< / _this>
  5.                     < specSet>
  6.                         < propSet>
  7.                             < type> VirtualMachine< / type>
  8.                             < all> 0< / all>
  9.                             < pathSet> name< / pathSet>
  10.                             < pathSet> guest. hostName< / pathSet>
  11.                             < pathSet> runtime. powerState< / pathSet>
  12.                             < pathSet> guest. ipAddress< / pathSet>
  13.                             < pathSet> guest. toolsRunningStatus< / pathSet>
  14.                         < / propSet>
  15.             < objectSet>
  16.                 < obj type= "VirtualMachine" > $ VM1ID$< / obj>
  17.             < / objectSet>
  18.             < objectSet>
  19.                 < obj type= "VirtualMachine" > $ VM2ID$< / obj>
  20.             < / objectSet>
  21.                     < / specSet>
  22.             < / RetrieveProperties>
  23.     < / soapenv:Body>
  24. < / soapenv:Envelope>
第四步,到这里,我们的准备工作就结束了,可以发送SOAP的控制消息,控制虚拟机的开关机/重起等操作了,这部分SOAP消息esxi-control.pl做得比较深入,值得借鉴。
这里只举一个重起虚拟机的SOAP消息做例子, $VMID$就是要被重起的虚拟机的ID
  1. < soap:Envelope xmlns:xsd= "http://www.w3.org/2001/XMLSchema" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:soap= "http://schemas.xmlsoap.org/soap/envelope/" >
  2.     < soap:Body>
  3.         < ResetVM_Task xmlns= "urn:internalvim25" >
  4.             < _this xsi:type= "VirtualMachine" type= "VirtualMachine" serverGuid= "" > $ VMID$< / _this>
  5.         < / ResetVM_Task>
  6.     < / soap:Body>
  7. < / soap:Envelope>
第五步,断开连接
  1. < soap:Envelope xmlns:xsd= "http://www.w3.org/2001/XMLSchema" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:soap= "http://schemas.xmlsoap.org/soap/envelope/" >
  2.     < soap:Body>
  3.         < Logout xmlns= "urn:internalvim25" >
  4.             < _this xsi:type= "ManagedObjectReference" type= "SessionManager" serverGuid= "" > ha-sessionmgr< / _this>
  5.             < / Logout>
  6.     < / soap:Body>
  7. < / soap:Envelope>

JAVA实现代码如下
  1. package java_vc;
  2. /**
  3.  *
  4.  * @author yyz_tj_cn@sina.com.cn
  5.  */
  6. import org . apache. http. Header;
  7. import org . apache. http. HttpEntity;
  8. import org . apache. http. HttpResponse;
  9. import org . apache. http. client. methods. HttpPost;
  10. import org . apache. http. impl. client. DefaultHttpClient;
  11. import org . apache. http. util . EntityUtils;
  12. import javax . net . ssl . SSLContext ;
  13. import org . apache. http. conn. ssl . SSLSocketFactory ;
  14. import javax . net . ssl . TrustManager ;
  15. import javax . net . ssl . X509TrustManager ;
  16. import java . security . cert . X509Certificate ;
  17. import java . security . cert . CertificateException ;
  18. import org . apache. http. conn. scheme. Scheme;
  19. import org . apache. http. entity . StringEntity;
  20. import org . apache. http. client. params . ClientPNames;
  21. import org . apache. http. client. params . CookiePolicy;
  22. import org . w3c . dom . Document ;
  23. import org . w3c . dom . NodeList ;
  24. import javax . xml . parsers . * ;
  25. import java . util . * ;
  26. public class Vmoperation {
  27.     //This Embeded Class is used to store Virtual Machine information
  28.     public class Vminfo {
  29.         private String id = null ;
  30.         private String name = null ;
  31.         private String networkName = null ;
  32.         private String ipv4 = null ;
  33.         private String powerState = null ;
  34.         private String vmToolRunningSattus = null ;
  35.         public Vminfo( ) {
  36.         }
  37.         public String getID ( ) {
  38.             return id ;
  39.         }
  40.         public void setID ( String val) {
  41.             id = val. trim ( ) ;
  42.         }
  43.         public String getName ( ) {
  44.             return name ;
  45.         }
  46.         public void setName ( String val) {
  47.             name = val. trim ( ) ;
  48.         }
  49.         public String getNetworkName( ) {
  50.             return networkName;
  51.         }
  52.         public void setNetworkName( String val) {
  53.             networkName= val. trim ( ) ;
  54.         }
  55.         public String getIpAddress( ) {
  56.             return ipv4;
  57.         }
  58.         public void setIpAddress( String val) {
  59.             ipv4= val. trim ( ) ;
  60.         }
  61.         public String getPowerState( ) {
  62.             return powerState;
  63.         }
  64.         public void setPowerState( String val) {
  65.             powerState= val. trim ( ) ;
  66.         }
  67.         public String getVMToolRunningSattus( ) {
  68.             return vmToolRunningSattus;
  69.         }
  70.         public void setVMToolRunningSattus( String val) {
  71.             vmToolRunningSattus= val. trim ( ) ;
  72.         }
  73.     }
  74.     //Vmoperation Class start...
  75.     private boolean debug = true;
  76.     private boolean connected = false;
  77.     private DefaultHttpClient httpclient = null ;
  78.     private TrustManager easyTrustManager = null ;
  79.     private ArrayList vmList = null ;
  80.     private String hostURL = null ;
  81.     private String xml_login = "<soap:Envelope xmlns:xsd=/"http://www.w3.org/2001/XMLSchema/" xmlns:xsi=/"http://www.w3.org/2001/XMLSchema-instance/" xmlns:soap=/"http://schemas.xmlsoap.org/soap/envelope//"> " +
  82.                 "<soap:Body>" +
  83.                     "<Login xmlns=/"urn:internalvim25/">" +
  84.                         "<_this xsi:type=/"SessionManager/" type=/"SessionManager/" serverGuid=/"/">ha-sessionmgr</_this>" +
  85.                         "<userName>$USERNAME$</userName>" +
  86.                         "<password>$PASSWORD$</password>" +
  87.                         "<locale>en_US</locale>" +
  88.                     "</Login>" +
  89.                 "</soap:Body>" +
  90.             "</soap:Envelope>" ;
  91.     private String xml_logout = "<soap:Envelope xmlns:xsd=/"http://www.w3.org/2001/XMLSchema/" xmlns:xsi=/"http://www.w3.org/2001/XMLSchema-instance/" xmlns:soap=/"http://schemas.xmlsoap.org/soap/envelope//">" +
  92.                 "<soap:Body>" +
  93.                     "<Logout xmlns=/"urn:internalvim25/">" +
  94.                         "<_this xsi:type=/"ManagedObjectReference/" type=/"SessionManager/" serverGuid=/"/">ha-sessionmgr</_this>" +
  95.                         "</Logout>" +
  96.                 "</soap:Body>" +
  97.             "</soap:Envelope>" ;
  98.     private String xml_poweroff = "<soap:Envelope xmlns:xsd=/"http://www.w3.org/2001/XMLSchema/" xmlns:xsi=/"http://www.w3.org/2001/XMLSchema-instance/" xmlns:soap=/"http://schemas.xmlsoap.org/soap/envelope//">" +
  99.                     "<soap:Body>" +
  100.                         "<PowerOffVM_Task xmlns=/"urn:internalvim25/">" +
  101.                           "<_this xsi:type=/"VirtualMachine/" type=/"VirtualMachine/" serverGuid=/"/">$VMID$</_this>" +
  102.                         "</PowerOffVM_Task>" +
  103.                     "</soap:Body>" +
  104.                    "</soap:Envelope>" ;
  105.     private String xml_poweron = "<soap:Envelope xmlns:xsd=/"http://www.w3.org/2001/XMLSchema/" xmlns:xsi=/"http://www.w3.org/2001/XMLSchema-instance/" xmlns:soap=/"http://schemas.xmlsoap.org/soap/envelope//">" +
  106.                     "<soap:Body>" +
  107.                         "<PowerOnVM_Task xmlns=/"urn:internalvim25/">" +
  108.                             "<_this xsi:type=/"VirtualMachine/" type=/"VirtualMachine/" serverGuid=/"/">$VMID$</_this>" +
  109.                         "</PowerOnVM_Task>" +
  110.                     "</soap:Body>" +
  111.                 "</soap:Envelope>" ;
  112.     private String xml_reset = "<soap:Envelope xmlns:xsd=/"http://www.w3.org/2001/XMLSchema/" xmlns:xsi=/"http://www.w3.org/2001/XMLSchema-instance/" xmlns:soap=/"http://schemas.xmlsoap.org/soap/envelope//">" +
  113.                     "<soap:Body>" +
  114.                         "<ResetVM_Task xmlns=/"urn:internalvim25/">" +
  115.                             "<_this xsi:type=/"VirtualMachine/" type=/"VirtualMachine/" serverGuid=/"/">$VMID$</_this>" +
  116.                         "</ResetVM_Task>" +
  117.                     "</soap:Body>" +
  118.                 "</soap:Envelope>" ;
  119.      private String xml_getVMIDs = "<soapenv:Envelope xmlns:soapenv=/"http://schemas.xmlsoap.org/soap/envelope//" xmlns:xsd=/"http://www.w3.org/2001/XMLSchema/" xmlns:xsi=/"http://www.w3.org/2001/XMLSchema-instance/">" +
  120.                                 "<soapenv:Body>" +
  121.                                         "<RetrieveProperties xmlns=/"urn:vim25/">" +
  122.                                                 "<_this type=/"PropertyCollector/">ha-property-collector</_this>" +
  123.                                                 "<specSet>" +
  124.                                                         "<propSet>" +
  125.                                                                 "<type>HostSystem</type>" +
  126.                                                                 "<all>0</all>" +
  127.                                                                 "<pathSet>vm</pathSet>" +
  128.                                                         "</propSet>" +
  129.                                                         "<objectSet>" +
  130.                                                                 "<obj type=/"HostSystem/">ha-host</obj>" +
  131.                                                         "</objectSet>" +
  132.                                                 "</specSet>" +
  133.                                         "</RetrieveProperties>" +
  134.                                 "</soapenv:Body>" +
  135.                         "</soapenv:Envelope>" ;
  136.     private String xml_getVMInfo = "<soapenv:Envelope xmlns:soapenv=/"http://schemas.xmlsoap.org/soap/envelope//" xmlns:xsd=/"http://www.w3.org/2001/XMLSchema/" xmlns:xsi=/"http://www.w3.org/2001/XMLSchema-instance/">" +
  137.                                     "<soapenv:Body>" +
  138.                                             "<RetrieveProperties xmlns=/"urn:vim25/">" +
  139.                                                 "<_this type=/"PropertyCollector/">ha-property-collector</_this>" +
  140.                                                     "<specSet>" +
  141.                                                         "<propSet>" +
  142.                                                             "<type>VirtualMachine</type>" +
  143.                                                             "<all>0</all>" +
  144.                                                             "<pathSet>name</pathSet>" +
  145.                                                             "<pathSet>guest.hostName</pathSet>" +
  146.                                                             "<pathSet>runtime.powerState</pathSet>" +
  147.                                                             "<pathSet>guest.ipAddress</pathSet>" +
  148.                                                             "<pathSet>guest.toolsRunningStatus</pathSet>" +
  149.                                                         "</propSet>" +
  150.                                                         "$VMIDLISTOBJ$" +
  151.                                                     "</specSet>" +
  152.                                             "</RetrieveProperties>" +
  153.                                     "</soapenv:Body>" +
  154.                             "</soapenv:Envelope>" ;
  155.     
  156.     //Connect to ESXi Host
  157.     public String Connect ( String IPAddress, String Username, String Password) throws Exception {
  158.         //Clear previous connection, if any.
  159.         if ( connected) {
  160.             Disconnect ( ) ;
  161.             finalCleanup( ) ;
  162.         }
  163.         debugOutput( "Connecting to host " + ip2URL( IPAddress) ) ;
  164.         //Init new connection
  165.         hostURL = ip2URL( IPAddress) ;
  166.         httpclient = new DefaultHttpClient( ) ;
  167.         //Init a customer X509TrustManager to trust any certificates
  168.         easyTrustManager = new X509TrustManager ( ) {
  169.             @Override
  170.             public void checkClientTrusted (
  171.                 X509Certificate [ ] chain,
  172.                 String authType) throws CertificateException {
  173.                 // Oh, I am easy!
  174.             }
  175.             @Override
  176.             public void checkServerTrusted (
  177.                 X509Certificate [ ] chain,
  178.                 String authType) throws CertificateException {
  179.                 // Oh, I am easy!
  180.             }
  181.             @Override
  182.             public X509Certificate [ ] getAcceptedIssuers ( ) {
  183.                 return null ;
  184.             }
  185.         } ;
  186.         SSLContext sslcontext = SSLContext . getInstance ( "TLS" ) ;
  187.         sslcontext . init ( null , new TrustManager [ ] { easyTrustManager } , null ) ;
  188.         //Init SSLSocketFactory to accept any hostname and any certificates
  189.         SSLSocketFactory sf = new SSLSocketFactory ( sslcontext , SSLSocketFactory . ALLOW_ALL_HOSTNAME_VERIFIER) ;
  190.         Scheme sch = new Scheme( "https" , 443, sf) ;
  191.         httpclient. getConnectionManager( ) . getSchemeRegistry( ) . register ( sch) ;
  192.         httpclient. getParams ( ) . setParameter ( ClientPNames. COOKIE_POLICY, CookiePolicy. BROWSER_COMPATIBILITY) ;
  193.         //Send Hello Message
  194.         xml_login = xml_login. replace ( "$USERNAME$" , Username) ;
  195.         xml_login = xml_login. replace ( "$PASSWORD$" , Password) ;
  196.         HttpResponse result ;
  197.         result = sendXML( hostURL, xml_login) ;
  198.         if ( debug) dispalyHttpResponse( result ) ; else EntityUtils. consume ( result . getEntity ( ) ) ;
  199.         //If not HTTP 200 returned, error occured.
  200.         if ( result . getStatusLine( ) . toString ( ) . trim ( ) . equals ( "HTTP/1.1 200 OK" ) ) connected= true;
  201.         //Get Virtual Machine List
  202.         if ( connected) vmList= getVMList( ) ;
  203.         
  204.         //Return connect result
  205.         return result . getStatusLine( ) . toString ( ) ;
  206.     }
  207.     //disconnect from ESXi Host
  208.     public String Disconnect ( ) throws Exception {
  209.         String ret = null ;
  210.         if ( debug) System . out. println ( "Disconnecting from host " + hostURL) ;
  211.         if ( connected) {
  212.             HttpResponse result = null ;
  213.             result = sendXML( hostURL, xml_logout) ;
  214.             if ( debug) dispalyHttpResponse( result ) ; else EntityUtils. consume ( result . getEntity ( ) ) ;
  215.             //If not HTTP 200 returned, error occured.
  216.             if ( result . getStatusLine( ) . toString ( ) . trim ( ) . equals ( "HTTP/1.1 200 OK" ) ) {
  217.                 finalCleanup( ) ;
  218.             }
  219.             ret = result . getStatusLine( ) . toString ( ) ;
  220.         }
  221.         //Return connect result
  222.         return ret;
  223.     }
  224.     //Display Virtual Machine List on connected ESXi Host
  225.     public void DisplayVMList ( ) {
  226.         debugOutput( "Displaying Virtual Machine List..." ) ;
  227.         //init Column Width
  228.         int width1= 3, width2= 12, width3= 12, width4= 10, width5= 12, width6= 21;
  229.         if ( vmList ! = null ) {
  230.             //Get Col width
  231.             for ( int i= 0; i< vmList. size ( ) ; i+ + ) {
  232.                 Vminfo VMNode= null ;
  233.                 VMNode= ( Vminfo) vmList. get ( i) ;
  234.                 if ( VMNode. getID ( ) ! = null ) width1 = Math . max ( VMNode. getID ( ) . length ( ) , width1) ;
  235.                 if ( VMNode. getName ( ) ! = null ) width2 = Math . max ( VMNode. getName ( ) . length ( ) , width2) ;
  236.                 if ( VMNode. getNetworkName( ) ! = null ) width3 = Math . max ( VMNode. getNetworkName( ) . length ( ) , width3) ;
  237.                 if ( VMNode. getIpAddress( ) ! = null ) width4 = Math . max ( VMNode. getIpAddress( ) . length ( ) , width4) ;
  238.                 if ( VMNode. getPowerState( ) ! = null ) width5 = Math . max ( VMNode. getPowerState( ) . length ( ) , width5) ;
  239.                 if ( VMNode. getVMToolRunningSattus( ) ! = null ) width6 = Math . max ( VMNode. getVMToolRunningSattus( ) . length ( ) , width6) ;
  240.             }
  241.             //Output Result
  242.             //Title
  243.             String title = "" ;
  244.             title + = formatData( "ID" , width1) ;
  245.             title + = formatData( "Machine Name" , width2) ;
  246.             title + = formatData( "Network Name" , width3) ;
  247.             title + = formatData( "IP Address" , width4) ;
  248.             title + = formatData( "Power Status" , width5) ;
  249.             title + = formatData( "VMTool running Status" , width6) ;
  250.             title + = "/n" ;
  251.             for ( int i= 0; i< = width1+ width2+ width3+ width4+ width5+ width6+ 6; i+ + ) {
  252.                 title + = "-" ;
  253.             }
  254.             System . out. println ( title) ;
  255.             //Data
  256.             for ( int i= 0; i< vmList. size ( ) ; i+ + ) {
  257.                 Vminfo VMNode= null ;
  258.                 String output = "" ;
  259.                 VMNode= ( Vminfo) vmList. get ( i) ;
  260.                 output + = formatData( VMNode. getID ( ) , width1) ;
  261.                 output + = formatData( VMNode. getName ( ) , width2) ;
  262.                 output + = formatData( VMNode. getNetworkName( ) , width3) ;
  263.                 output + = formatData( VMNode. getIpAddress( ) , width4) ;
  264.                 output + = formatData( VMNode. getPowerState( ) , width5) ;
  265.                 output + = formatData( VMNode. getVMToolRunningSattus( ) , width6) ;
  266.                 System . out. println ( output ) ;
  267.             }
  268.         }
  269.     }
  270.     //Power-Off virtual machine on connected ESXi host
  271.     public String PowerOffVM ( String VMName) throws Exception {
  272.         String ret = null ;
  273.         debugOutput( "Powering Off " + VMName) ;
  274.         if ( connected) {
  275.             String xmldata = xml_poweroff. replace ( "$VMID$" , getVMId ( VMName) ) ;
  276.             HttpResponse result ;
  277.             result = sendXML( hostURL, xmldata) ;
  278.             if ( debug) dispalyHttpResponse( result ) ; else EntityUtils. consume ( result . getEntity ( ) ) ;
  279.             ret = result . getStatusLine( ) . toString ( ) ;
  280.         }
  281.         //Return result
  282.         return ret;
  283.     }
  284.     //Power-On virtual machine on connected ESXi host
  285.     public String PowerOnVM ( String VMName) throws Exception {
  286.         String ret = null ;
  287.         debugOutput( "Powering On " + VMName) ;
  288.         if ( connected) {
  289.             String xmldata = xml_poweron. replace ( "$VMID$" , getVMId ( VMName) ) ;
  290.             HttpResponse result ;
  291.             result = sendXML( hostURL, xmldata) ;
  292.             if ( debug) dispalyHttpResponse( result ) ; else EntityUtils. consume ( result . getEntity ( ) ) ;
  293.             ret = result . getStatusLine( ) . toString ( ) ;
  294.         }
  295.         //Return result
  296.         return ret;
  297.     }
  298.     //Reset virtual machine on connected ESXi host
  299.     public String ResetVM ( String VMName) throws Exception {
  300.         String ret = null ;
  301.         debugOutput( "Reseting " + VMName) ;
  302.         if ( connected) {
  303.             String xmldata = xml_reset. replace ( "$VMID$" , getVMId ( VMName) ) ;
  304.             HttpResponse result ;
  305.             result = sendXML( hostURL, xmldata) ;
  306.             if ( debug) dispalyHttpResponse( result ) ; else EntityUtils. consume ( result . getEntity ( ) ) ;
  307.             ret = result . getStatusLine( ) . toString ( ) ;
  308.         }
  309.         //Return result
  310.         return ret;
  311.     }
  312.     public boolean getConnected( ) {
  313.         return this . connected;
  314.     }
  315.     private void finalCleanup( ) {
  316.         if ( httpclient!=null) httpclient. getConnectionManager( ) . shutdown ( ) ;
  317.         connected= false;
  318.         vmList= null ;
  319.         httpclient = null ;
  320.         easyTrustManager = null ;
  321.         hostURL = null ;
  322.     }
  323.     //Get VMID from given virtual machine name
  324.     private String getVMId ( String VMName) {
  325.         String result = null ;
  326.         Iterator it = vmList. iterator ( ) ;
  327.         while ( it. hasNext ( ) ) {
  328.             Vminfo VMNode = null ;
  329.             VMNode = ( Vminfo) it. next ( ) ;
  330.             if ( VMName. toLowerCase ( ) . trim ( ) . equals ( VMNode. getName ( ) . toLowerCase ( ) ) ) {
  331.                 result = VMNode. getID ( ) ;
  332.                 break ;
  333.             }
  334.         }
  335.         return result ;
  336.     }
  337.     //Get All Virtual Machine Information on connected ESXi host
  338.     private ArrayList getVMList( ) throws Exception {
  339.         ArrayList result = new ArrayList ( ) ;
  340.         Vminfo VMNode = null ;
  341.         HttpResponse rspVMList = sendXML( hostURL, genXML_getVMInfo( getVMIDs ( ) ) ) ;
  342.         //Parse returned XML and store information in vmList
  343.         //NEED MORE SMART!!!
  344.         //Returned XML sample
  345.         /*
  346.         <returnval>
  347.         <obj type="VirtualMachine">128</obj>
  348.         <propSet><name>guest.hostName</name><val xsi:type="xsd:string">aaa.ccc.bbb</val></propSet>
  349.         <propSet><name>guest.ipAddress</name><val xsi:type="xsd:string">aaa.ccc.bbb</val></propSet>
  350.         <propSet><name>guest.toolsRunningStatus</name><val xsi:type="xsd:string">guestToolsRunning</val></propSet>
  351.         <propSet><name>name</name><val xsi:type="xsd:string">aaa.ccc.bbb</val></propSet>
  352.         <propSet><name>runtime.powerState</name><val xsi:type="VirtualMachinePowerState">poweredOn</val></propSet>
  353.         </returnval>
  354.         <returnval>
  355.         <obj type="VirtualMachine">240</obj>
  356.         <propSet><name>guest.toolsRunningStatus</name><val xsi:type="xsd:string">guestToolsNotRunning</val></propSet>
  357.         <propSet><name>name</name><val xsi:type="xsd:string">vSphere Management Assistant (vMA)</val></propSet>
  358.         <propSet><name>runtime.powerState</name><val xsi:type="VirtualMachinePowerState">poweredOff</val></propSet>
  359.         </returnval>
  360.          *
  361.          *
  362.          */
  363.         DocumentBuilderFactory dbf = DocumentBuilderFactory . newInstance ( ) ;
  364.         DocumentBuilder db = dbf. newDocumentBuilder ( ) ;
  365.         Document doc = db. parse ( rspVMList. getEntity ( ) . getContent ( ) ) ;
  366.         NodeList nl1 = doc . getElementsByTagName ( "returnval" ) ;
  367.         //<returnval>
  368.         for ( int i= 0; i< nl1. getLength ( ) ; i+ + ) {
  369.             if ( nl1. item ( i) . hasChildNodes ( ) ) {
  370.                 VMNode = new Vminfo( ) ;
  371.                 NodeList nl2 = nl1. item ( i) . getChildNodes ( ) ;
  372.                 //<obj>&<proSet>
  373.                 for ( int j= 0; j< nl2. getLength ( ) ; j+ + ) {
  374.                     if ( nl2. item ( j) . getNodeName ( ) . trim ( ) . equals ( "obj" ) ) {
  375.                         VMNode. setID ( nl2. item ( j) . getTextContent ( ) ) ;
  376.                     }
  377.                     else {
  378.                         if ( nl2. item ( j) . hasChildNodes ( ) ) {
  379.                             NodeList nl3 = nl2. item ( j) . getChildNodes ( ) ;
  380.                             //<proset>
  381.                             //There are 2 childnodes in <proset>, one is for value name, another is value, it's a pair. so k+=2
  382.                             for ( int k= 0; k< nl3. getLength ( ) ; k+ = 2) {
  383.                                 if ( nl3. item ( k) . getTextContent ( ) . trim ( ) . toLowerCase ( ) . equals ( "name" ) & & nl3. item ( k+ 1) . getNodeName ( ) . trim ( ) . toLowerCase ( ) . equals ( "val" ) ) {
  384.                                     VMNode. setName ( nl3. item ( k+ 1) . getTextContent ( ) ) ;
  385.                                 } else if ( nl3. item ( k) . getTextContent ( ) . trim ( ) . toLowerCase ( ) . equals ( "guest.hostname" ) & & nl3. item ( k+ 1) . getNodeName ( ) . trim ( ) . toLowerCase ( ) . equals ( "val" ) ) {
  386.                                     VMNode. setNetworkName( nl3. item ( k+ 1) . getTextContent ( ) ) ;
  387.                                 } else if ( nl3. item ( k) . getTextContent ( ) . trim ( ) . toLowerCase ( ) . equals ( "runtime.powerstate" ) & & nl3. item ( k+ 1) . getNodeName ( ) . trim ( ) . toLowerCase ( ) . equals ( "val" ) ) {
  388.                                     VMNode. setPowerState( nl3. item ( k+ 1) . getTextContent ( ) ) ;
  389.                                 } else if ( nl3. item ( k) . getTextContent ( ) . trim ( ) . toLowerCase ( ) . equals ( "guest.toolsrunningstatus" ) & & nl3. item ( k+ 1) . getNodeName ( ) . trim ( ) . toLowerCase ( ) . equals ( "val" ) ) {
  390.                                     VMNode. setVMToolRunningSattus( nl3. item ( k+ 1) . getTextContent ( ) ) ;
  391.                                 } else if ( nl3. item ( k) . getTextContent ( ) . trim ( ) . toLowerCase ( ) . equals ( "guest.ipaddress" ) & & nl3. item ( k+ 1) . getNodeName ( ) . trim ( ) . toLowerCase ( ) . equals ( "val" ) ) {
  392.                                     VMNode. setIpAddress( nl3. item ( k+ 1) . getTextContent ( ) ) ;
  393.                                 }
  394.                             }
  395.                         }
  396.                     }
  397.                 }
  398.                 result . add ( VMNode) ;
  399.                 debugOutput ( "1 VM Added. VMID=" + VMNode. getID ( ) + " VMName=" + VMNode. getName ( ) + " VMNetworkName=" + VMNode. getNetworkName( ) + " VMIP=" + VMNode. getIpAddress( ) + " VMPower=" + VMNode. getPowerState( ) + " ToolStatus=" + VMNode. getVMToolRunningSattus( ) ) ;
  400.             }
  401.         }
  402.         return result ;
  403.     }
  404.     private void debugOutput ( String msg) {
  405.         if ( debug) System . out. println ( "/n<DEBUG TYPE=MSG>/n" + msg+ "/n</DEBUG>" ) ;
  406.     }
  407.     //Get VMID list on a connected ESXi
  408.     private String [ ] getVMIDs ( ) throws Exception {
  409.         String [ ] result = null ;
  410.         //Sent xml to host to get VM ID list
  411.         HttpResponse rspVMIDList = sendXML( hostURL, xml_getVMIDs) ;
  412.         //Parse returned XML
  413.         DocumentBuilderFactory dbf = DocumentBuilderFactory . newInstance ( ) ;
  414.         DocumentBuilder db = dbf. newDocumentBuilder ( ) ;
  415.         Document doc = db. parse ( rspVMIDList. getEntity ( ) . getContent ( ) ) ;
  416.         NodeList nl1 = doc . getElementsByTagName ( "ManagedObjectReference" ) ;
  417.         //init the return value array
  418.         result = new String [ nl1. getLength ( ) ] ;
  419.         //set return array
  420.         for ( int i= 0; i< nl1. getLength ( ) ; i+ + ) {
  421.             //make sure the ID is for Virtual Machine
  422.             if ( nl1. item ( i) . hasChildNodes ( ) & &
  423.                 nl1. item ( i) . getAttributes ( ) . getNamedItem ( "type" ) . toString ( ) . trim ( ) . equals ( "type=/"VirtualMachine/"" ) ) {
  424.                 result [ i] = nl1. item ( i) . getFirstChild ( ) . getNodeValue ( ) . toString ( ) . trim ( ) ;
  425.                 debugOutput( "VMID=" + result [ i] ) ;
  426.             }
  427.         }
  428.         return result ;
  429.     }
  430.     private String genXML_getVMInfo( String [ ] vmIDList) {
  431.         String result ;
  432.         String tmpxml= "" ;
  433.         for ( int i= 0; i< vmIDList. length ; i+ + ) {
  434.             tmpxml + = "<objectSet><obj type=/"VirtualMachine/">" + vmIDList[ i] + "</obj></objectSet>" ;
  435.         }
  436.         result = xml_getVMInfo. replace ( "$VMIDLISTOBJ$" , tmpxml) ;
  437.         debugOutput( result ) ;
  438.         return result ;
  439.     }
  440.     private void dispalyHttpResponse ( HttpResponse rsp) throws Exception {
  441.         HttpEntity entity = rsp. getEntity ( ) ;
  442.         System . out. println ( "********************<HTTP Response>********************" ) ;
  443.         System . out. println ( "----------------------<HEADERS>------------------------" ) ;
  444.         System . out. println ( rsp. getStatusLine( ) ) ;
  445.         Header[ ] headers = rsp. getAllHeaders( ) ;
  446.         for ( int i = 0; i < headers. length ; i+ + ) {
  447.             System . out. println ( headers[ i] ) ;
  448.         }
  449.         System . out. println ( "-----------------------<BODYS>-------------------------" ) ;
  450.         if ( entity ! = null ) {
  451.             System . out. println ( EntityUtils. toString ( entity ) ) ;
  452.         }
  453.         System . out. println ( "************************<END>*************************" ) ;
  454.         System . out. println ( ) ;
  455.         System . out. println ( ) ;
  456.     }
  457.     private HttpResponse sendXML( String URL , String xml ) throws Exception {
  458.         HttpPost httppost = new HttpPost( URL ) ;
  459.         StringEntity myEntity = new StringEntity( xml ) ;
  460.         httppost. addHeader( "Content-Type" , "text/xml; charset=/"utf-8/"" ) ;
  461.         httppost. addHeader( "User-Agent" , "VMware VI Client/4.1.0" ) ;
  462.         httppost. addHeader( "SOAPAction" , "/"urn:internalvim25/4.0/"" ) ;
  463.         httppost. setEntity( myEntity) ;
  464.         if ( debug) System . out. println ( "executing request to " + httppost) ;
  465.         HttpResponse rsp = httpclient. execute ( httppost) ;
  466.         return rsp;
  467.     }
  468.     private String ip2URL ( String IPAddress) {
  469.         return "HTTPS://" + IPAddress+ "/sdk/" ;
  470.     }
  471.     private String formatData ( String data, int width ) {
  472.         String result ;
  473.         
  474.         if ( data!=null) {
  475.             result = data;
  476.         } else {
  477.             result = "N/A" ;
  478.         }
  479.         //Append space
  480.         for ( int i= result . length ( ) ; i< = width ; i+ + ) {
  481.             result + = " " ;
  482.         }
  483.         return result ;
  484.     }
  485.     
  486.      public static void main( String [ ] args) throws Exception {
  487.         Vmoperation temp = new Vmoperation( ) ;
  488.         System . out. println ( temp. Connect ( "<Your ESXi IP>" , "<Username>" , "<Password>" ) ) ;
  489.         System . in . read ( ) ;
  490.         System . out. println ( temp. PowerOffVM( "New Virtual Machine" ) ) ;
  491.         System . in . read ( ) ;
  492.         temp. DisplayVMList( ) ;
  493.         System . in . read ( ) ;
  494.         System . out. println ( temp. PowerOnVM( "New Virtual Machine" ) ) ;
  495.         System . in . read ( ) ;
  496.         System . out. println ( temp. ResetVM( "New Virtual Machine" ) ) ;
  497.         System . in . read ( ) ;
  498.         System . out. println ( temp. Disconnect ( ) ) ;
  499.      }
  500. }

注:以上仅用于学术研究,禁止用于实际生产环境。否则将导致违反VMWare License Agreement. VMWare可能随时改变XML的定义,导致程序不能正常工作。
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐