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