Windows下Libvirt Java API使用教程(二)- 接口使用說明

 介紹完libvirt Java API的部署工作:

Windows下Libvirt Java API使用教程(一)- 開發環境部署

接下來我們就介紹一下接口的使用和代碼樣例。

libvirt的管理單位是單個主機,所以探測和監控接口所能獲取的信息的最大範圍也是主機。所以先從主機入手,驗證libvirt接口。主機(libvirt所在管理節點)探測相關接口驗證代碼如下:
  1. @Before 
  2.     public void init() { 
  3.         System.setProperty("jna.library.path"
  4.                 "D:/Git-Repo/git/libvirt-java/libvirt-java/src/test/java/kubi/coder/"); 
  5.         try { 
  6.             xenConn = new Connect("xen+tcp://10.4.55.203/"); 
  7.             // system代表擁有系統權限/session是用戶權限 
  8.             kvmConn = new Connect("qemu+tcp://10.4.54.10/system"); 
  9.         } catch (LibvirtException e) { 
  10.             e.printStackTrace(); 
  11.         } 
  12.     } 
  13.  
  14.     /** 
  15.      * 主機信息探測接口驗證,驗證可以獲取的主機屬性和監控指標,分別考慮Xen環境和KVM環境 
  16.      *  
  17.      *  
  18.      * @author lihzh 
  19.      * @date 2012-5-15 下午1:28:00 
  20.      */ 
  21.     @Test 
  22.     public void testDetectHost() { 
  23.         // KVM 
  24.         doDetectHost(kvmConn); 
  25.         // XEN 
  26.         doDetectHost(xenConn); 
  27.     } 
  28.  
  29.     /** 
  30.      * 執行探測主機測試函數 
  31.      *  
  32.      * @param conn 
  33.      * @author lihzh 
  34.      * @date 2012-5-15 下午1:37:37 
  35.      */ 
  36.     private void doDetectHost(Connect conn) { 
  37.         try { 
  38.             // Returns the free memory for the connection 
  39.             // System.out.println("FreeMemory: " + conn.getFreeMemory());// 不支持 
  40.              
  41.             // Returns the system hostname on which the hypervisor is running. 
  42.             // (the result of the gethostname(2) system call) 
  43.             // If we are connected to a remote system, 
  44.             // then this returns the hostname of the remote system 
  45.             System.out.println("Host name: " + conn.getHostName()); 
  46.             // Gets the name of the Hypervisor software used. 
  47.             System.out.println("Type: " + conn.getType()); 
  48.             // Gets the version level of the Hypervisor running. This may work 
  49.             // only with hypervisor call, i.e. with priviledged access to the 
  50.             // hypervisor, not with a Read-Only connection. If the version can't 
  51.             // be extracted by lack of capacities returns 0. 
  52.             // Returns: 
  53.             // major * 1,000,000 + minor * 1,000 + release 
  54.             System.out.println(conn.getVersion()); 
  55.  
  56.             NodeInfo nodeInfo = conn.nodeInfo(); 
  57.             System.out.println("the number of active CPUs: " + nodeInfo.cpus); 
  58.             System.out.println("number of core per socket: " + nodeInfo.cores); 
  59.             System.out.println("memory size in kilobytes: " + nodeInfo.memory); 
  60.             System.out.println("expected CPU frequency: " + nodeInfo.mhz); 
  61.             System.out.println("string indicating the CPU model: " 
  62.                     + nodeInfo.model); 
  63.             System.out.println("the number of NUMA cell, 1 for uniform: " 
  64.                     + nodeInfo.nodes); 
  65.             System.out.println("number of CPU socket per node: " 
  66.                     + nodeInfo.sockets); 
  67.             System.out.println("number of threads per core: " 
  68.                     + nodeInfo.threads); 
  69.             System.out 
  70.                     .println("the total number of CPUs supported but not necessarily active in the host.: " 
  71.                             + nodeInfo.maxCpus()); 
  72.  
  73.             // for (String interName : conn.listInterfaces()) { 
  74.             // System.out.println(interName); 
  75.             // } 不支持 
  76.  
  77.             // Provides the list of names of defined interfaces on this host 
  78.  
  79.             // for (String interName : conn.listDefinedInterfaces()) { 
  80.             // System.out.println(interName); 
  81.             // } // 不支持 
  82.  
  83.             // Lists the active networks. 
  84.             for (String networkName : conn.listNetworks()) { 
  85.                 System.out.println("Network name: " + networkName); 
  86.             } 
  87.  
  88.             // Lists the names of the network filters 
  89.             for (String networkFilterName : conn.listNetworkFilters()) { 
  90.                 System.out.println("Network filter name: " + networkFilterName); 
  91.             } 
  92.  
  93.             System.out.println(conn.getCapabilities()); 
  94.         } catch (LibvirtException e) { 
  95.             e.printStackTrace(); 
  96.         } 
  97.     } 
  98.  

 分別在KVM和XEN環境下測試了libvirt接口,測試結果如下:

Host name: s5410
Type: QEMU
9001
the number of active CPUs: 64
number of core per socket: 8
memory size in kilobytes: 49444896
expected CPU frequency: 2131
string indicating the CPU model: x86_64
the number of NUMA cell, 1 for uniform: 1
number of CPU socket per node: 4
number of threads per core: 2
the total number of CPUs supported but not necessarily active in the host.: 64
Network name: hello
Network name: default
Network filter name: no-other-l2-traffic
Network filter name: allow-dhcp
...
<capabilities>
 
  <host>
    <uuid>30b940dd-f79a-21a2-82d5-ddc1b1b4a7e4</uuid>
    <cpu>
      <arch>x86_64</arch>
      <model>core2duo</model>
      <topology sockets='4' cores='8' threads='2'/>
      <feature name='lahf_lm'/>
      <feature name='rdtscp'/>
       ...
    </cpu>
    <migration_features>
      <live/>
      <uri_transports>
        <uri_transport>tcp</uri_transport>
      </uri_transports>
    </migration_features>
  </host>
 
  <guest>
    <os_type>hvm</os_type>
    <arch name='i686'>
      <wordsize>32</wordsize>
      <emulator>/usr/libexec/qemu-kvm</emulator>
      <machine>rhel5.4.0</machine>
      <machine canonical='rhel5.4.0'>pc</machine>
      <machine>rhel5.4.4</machine>
      <machine>rhel5.5.0</machine>
      <machine>rhel5.6.0</machine>
      <domain type='qemu'>
      </domain>
      <domain type='kvm'>
        <emulator>/usr/libexec/qemu-kvm</emulator>
      </domain>
    </arch>
    <features>
      <cpuselection/>
      <pae/>
      <nonpae/>
      <acpi default='on' toggle='yes'/>
      <apic default='on' toggle='no'/>
    </features>
  </guest>
 
 ...
 
</capabilities>
 
Host name: s55203
Type: Xen
3001000
the number of active CPUs: 32
number of core per socket: 8
memory size in kilobytes: 50276352
expected CPU frequency: 1995
string indicating the CPU model: x86_64
the number of NUMA cell, 1 for uniform: 1
number of CPU socket per node: 2
number of threads per core: 2
the total number of CPUs supported but not necessarily active in the host.: 32
Network name: default
Network filter name: allow-dhcp-server
Network filter name: qemu-announce-self-rarp
...
<capabilities>
 
  <host>
    <cpu>
      <arch>x86_64</arch>
      <features>
        <vmx/>
      </features>
    </cpu>
    <migration_features>
      <live/>
      <uri_transports>
        <uri_transport>xenmigr</uri_transport>
      </uri_transports>
    </migration_features>
  </host>
 
  <guest>
    <os_type>xen</os_type>
    <arch name='x86_64'>
      <wordsize>64</wordsize>
      <emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
      <machine>xenpv</machine>
      <domain type='xen'>
      </domain>
    </arch>
  </guest>
 
  ... 
</capabilities>
 
說明:

注1:標註不支持的,是在當前環境當前libvirt版本下,運行會報錯的接口。

  unsupported in sys interface

注2:名詞解釋

hvm:
gives similar information but when running a 32 bit OS fully virtualized with Xen using the hvm support。

numa:
For processors that support hyperthreading, this is the number of hyperthreads
they have per core.  On a machine that doesn't support hyperthreading, this
will be 1.


說實話,這麼多信息中,筆者關注的不多,有很多甚至說不出其代表的含義,筆者關注只是cpu的個數,核心數,內存總量等直觀信息。有就足以。
看完了主機,再看看虛擬機。一個虛擬化環境中的核心資源自然是虛擬機,所以其屬性和信息也自然多很多,上測試代碼:

  1. /**  
  2.      * 測試探測虛擬機接口  
  3.      *   
  4.      * @author lihzh  
  5.      * @date 2012-5-16 上午11:14:20  
  6.      */ 
  7.     @Test 
  8.     public void testDetectDomains() {  
  9.         // KVM  
  10.         doDetectDomains(kvmConn);  
  11.         // XEN  
  12.         doDetectDomains(xenConn);  
  13.     }  
  14.  
  15. /**  
  16.      * 執行探測虛擬機測試函數  
  17.      *   
  18.      * @param conn  
  19.      * @author lihzh  
  20.      * @date 2012-5-16 上午11:15:27  
  21.      */ 
  22.     private void doDetectDomains(Connect conn) {  
  23.         try {  
  24.             // Lists the active domains.(列出所有處於啓動(激活)狀態的虛擬機的id)  
  25.             for (int activeDomId : conn.listDomains()) {  
  26.                 System.out.println("Active vm id: " + activeDomId);  
  27.                 // 根據Id,探測各個虛擬機的詳細信息  
  28.                 Domain domain = conn.domainLookupByID(activeDomId);  
  29.                 // Gets the hypervisor ID number for the domain  
  30.                 System.out.println("Domain id: " + domain.getID());  
  31.                 // Gets the public name for this domain  
  32.                 System.out.println("Domain name: " + domain.getName());  
  33.                 // Gets the type of domain operation system.  
  34.                 System.out.println("Domain os type: " + domain.getOSType());  
  35.                 // Gets the UUID for this domain as string.  
  36.                 System.out.println("Domain uuid: " + domain.getUUIDString());  
  37.                 // Retrieve the maximum amount of physical memory allocated to a  
  38.                 // domain.  
  39.                 System.out.println("Domain max memory: " 
  40.                         + domain.getMaxMemory());  
  41.                 // Provides the maximum number of virtual CPUs supported for the  
  42.                 // guest VM. If the guest is inactive, this is basically the  
  43.                 // same as virConnectGetMaxVcpus. If the guest is running this  
  44.                 // will reflect the maximum number of virtual CPUs the guest was  
  45.                 // booted with.  
  46.                 System.out.println("Domain max vcpu: " + domain.getMaxVcpus());  
  47.                 // Provides an XML description of the domain. The description  
  48.                 // may be  
  49.                 // reused later to relaunch the domain with createLinux().  
  50.                 System.out.println("Domain xml description: " 
  51.                         + domain.getXMLDesc(0));  
  52.                 System.out.println("Domain maxMen allowed: " 
  53.                         + domain.getInfo().maxMem);  
  54.                 System.out.println("Domain memory: " + domain.getInfo().memory);  
  55.                 // domain.getJobInfo()  
  56.                 // 不支持  
  57.                 System.out.println("Domain state: " + domain.getInfo().state);  
  58.                 // Provides a boolean value indicating whether the network is  
  59.                 // configured to be automatically started when the host machine  
  60.                 // boots.  
  61.                 System.out.println("Domain network autostart: " 
  62.                         + domain.getAutostart());  
  63.                 // Extracts information about virtual CPUs of this domain  
  64.                 for (VcpuInfo vcpuInfo : domain.getVcpusInfo()) {  
  65.                     System.out.println("cpu: " + vcpuInfo.cpu);  
  66.                     System.out.println("cpu time: " + vcpuInfo.cpuTime);  
  67.                     System.out.println("cpu number: " + vcpuInfo.number);  
  68.                     System.out.println("cpu state: " + vcpuInfo.state);  
  69.                 }  
  70.               
  71.                 // 如果是KVM環境  
  72.                 if (conn.getURI().startsWith("qemu")) {  
  73.                     // This function returns block device (disk) stats for block  
  74.                     // devices attached to the domain  
  75.                     DomainBlockInfo blockInfo = domain  
  76.                             .blockInfo("/opt/awcloud/instance/admin/" 
  77.                                     + domain.getName() + "/disk");  
  78.                     System.out.println("Disk Capacity: " 
  79.                             + blockInfo.getCapacity());  
  80.                     System.out.println("Disk allocation: " 
  81.                             + blockInfo.getAllocation());  
  82.                     System.out.println("Disk physical: " 
  83.                             + blockInfo.getPhysical());  
  84.  
  85.                     DomainBlockStats blockStats = domain.blockStats("vda");  
  86.                     // 磁盤讀取請求總數  
  87.                     System.out.println("read request num: " + blockStats.rd_req);  
  88.                     // 磁盤讀取總bytes數  
  89.                     System.out.println("read request num: " + blockStats.rd_bytes);  
  90.                     // 磁盤寫入請求總數  
  91.                     System.out.println("read request num: " + blockStats.wr_req);  
  92.                     // 磁盤寫入總bytes數  
  93.                     System.out.println("read request num: " + blockStats.wr_bytes);  
  94.                 }  
  95.  
  96.             }  
  97.               
  98.             // 列出所有停止態的虛擬機  
  99.             for (String name : conn.listDefinedDomains()) {  
  100.                 System.out.println("Inactive domain name: " + name);  
  101.             }  
  102.  
  103.         } catch (LibvirtException e) {  
  104.             e.printStackTrace();  
  105.         }  
  106.     } 

循環較多,摘取部分結果如下:

Active vm id: 53
Domain id: 53
Domain name: i-546A099E
Domain os type: hvm
Domain uuid: e608560a-2c03-8e48-2e60-d0d01693f530
Domain max memory: 147456
Domain max vcpu: 1
Domain xml description: <domain type='xen' id='53'>
  <name>i-546A099E</name>
  <uuid>e608560a-2c03-8e48-2e60-d0d01693f530</uuid>
  <memory>131072</memory>
  <currentMemory>131072</currentMemory>
  <vcpu>1</vcpu>
  <os>
    <type>hvm</type>
    <loader>/usr/lib/xen/boot/hvmloader</loader>
    <boot dev='hd'/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <clock offset='utc'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <devices>
    <emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
    <disk type='file' device='disk'>
      <driver name='file'/>
      <source file='/opt/awcloud/instance/admin/i-546A099E/disk'/>
      <target dev='hda' bus='ide'/>
    </disk>
    <disk type='file' device='disk'>
      <driver name='file'/>
      <source file='/opt/awcloud/instance/admin/i-546A099E/disk2'/>
      <target dev='hdb' bus='ide'/>
    </disk>
    <interface type='bridge'>
      <mac address='d0:0d:54:6a:09:9e'/>
      <source bridge='xenbr0'/>
      <script path='vif-bridge'/>
      <target dev='vif53.0'/>
    </interface>
    <serial type='file'>
      <source path='/opt/awcloud/instance/admin/i-546A099E/console.log'/>
      <target port='0'/>
    </serial>
    <console type='file'>
      <source path='/opt/awcloud/instance/admin/i-546A099E/console.log'/>
      <target port='0'/>
    </console>
    <input type='tablet' bus='usb'/>
    <input type='mouse' bus='ps2'/>
    <graphics type='vnc' port='17237' autoport='no'/>
  </devices>
</domain>

Domain maxMen allowed: 147456
Domain memory: 139140
Domain state: VIR_DOMAIN_BLOCKED
Domain network autostart: false
cpu: 31
cpu time: 2225977676675
cpu number: 0
cpu state: VIR_VCPU_BLOCKED
Domain network autostart: false
Inactive domain name: i-46A70811
Inactive domain name: i-38C20705
Inactive domain name: i-498E09B2
Inactive domain name: null
Inactive domain name: null
Inactive domain name: null
Inactive domain name: null
Inactive domain name: null

 

結果分析:
結果中基本包含了一個虛擬機組成的全部元素信息。如果你想做一個監控系統,你可以發現這裏有:

虛擬機的名字
虛擬機的Id
虛擬機的內存大小
虛擬CPU個數
虛擬機磁盤文件信息,磁盤文件的大小。甚至包括log等信息。
虛擬磁盤讀寫速率。
虛擬機網絡設備信息。Mac地址,設備類型等。
虛擬機網卡讀寫速率。


基本可以滿足一個監控系統的需求。
說明一下上面的測試代碼。libvirt Java API的入口基本都是通過Connect這個類,也就是首先建立與被管理主機之間的連接:

  1. Connect kvmConn = new Connect("qemu+tcp://10.4.54.10/system"); 

然後通過該連接獲取信息:

  1. conn.listDomains() 

一個接口的如果需要接受參數:

  1. conn.domainLookupByID(activeDomId) 

肯定可以從其他的接口返回中找到答案:

  1. for (int activeDomId : conn.listDomains()) 

只是有的獲取的直接,有可能需要解析xml格式的返回值來獲取需要參數值。比如:disk的paht和interface的path。
最後再簡單介紹一下管控接口:

  1. /**  
  2.      * 測試虛擬機的簡單操作  
  3.      *   
  4.      * @author lihzh  
  5.      * @date 2012-5-16 下午3:35:43  
  6.      */ 
  7.     @Test 
  8.     public void testControlVM() {  
  9.         try {  
  10.             Domain domain = kvmConn.domainLookupByID(8);  
  11.             System.out.println("Domain state: " + domain.getInfo().state);  
  12.             domain.suspend();  
  13.             System.out.println("Domain state: " + domain.getInfo().state);  
  14.             for (int i = 0; i < 5; i++) {  
  15.                 System.out.println("wait for: " + (5 - i));  
  16.                 Thread.sleep(1000);  
  17.             }  
  18.             System.out.println("Resume vm.");  
  19.             domain.resume();  
  20.             System.out.println("Domain state: " + domain.getInfo().state);  
  21.         } catch (LibvirtException e) {  
  22.             e.printStackTrace();  
  23.         } catch (InterruptedException e) {  
  24.             e.printStackTrace();  
  25.         }  
  26.     } 

該用例主要測試了虛擬機的掛起和恢復操作。這類操作是比較簡單的(因爲無需參數)。一個複雜系統肯定需要包括虛擬機創建等操作。libvirt主要通過xml表述來創建資源,首先需要生成被創建虛擬機的完整描述,然後傳遞給創建的方法即可。描述的格式?呵呵,自然是上面測試結果給出的數據了。有興趣的,大家可以自己嘗試一下。libvirt的文檔,還不完善,不過對於創建這樣重要的功能,還是給出了說明。大家也可以下載官方的手冊作爲參考。
 

好了,相對於VMware、Xenserver等虛擬化平臺的SDK,libvirt的Java API還是比較簡單的,上手很快,結構很簡單。當然,功能上可能還是有所欠缺,信息量上,沒有其他的那麼充足。基於XML的方式操作資源,減少了接口的個數,使調用更直接,但是對開發人員卻增加了困難。不過仍不失爲一個不錯的虛擬機環境操作的API,尤其是針對KVM/XEN的環境來說,可謂不二的選擇。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章