介紹完libvirt Java API的部署工作:
《Windows下Libvirt Java API使用教程(一)- 開發環境部署》
接下來我們就介紹一下接口的使用和代碼樣例。
- @Before
- public void init() {
- System.setProperty("jna.library.path",
- "D:/Git-Repo/git/libvirt-java/libvirt-java/src/test/java/kubi/coder/");
- try {
- xenConn = new Connect("xen+tcp://10.4.55.203/");
- // system代表擁有系統權限/session是用戶權限
- kvmConn = new Connect("qemu+tcp://10.4.54.10/system");
- } catch (LibvirtException e) {
- e.printStackTrace();
- }
- }
- /**
- * 主機信息探測接口驗證,驗證可以獲取的主機屬性和監控指標,分別考慮Xen環境和KVM環境
- *
- *
- * @author lihzh
- * @date 2012-5-15 下午1:28:00
- */
- @Test
- public void testDetectHost() {
- // KVM
- doDetectHost(kvmConn);
- // XEN
- doDetectHost(xenConn);
- }
- /**
- * 執行探測主機測試函數
- *
- * @param conn
- * @author lihzh
- * @date 2012-5-15 下午1:37:37
- */
- private void doDetectHost(Connect conn) {
- try {
- // Returns the free memory for the connection
- // System.out.println("FreeMemory: " + conn.getFreeMemory());// 不支持
- // Returns the system hostname on which the hypervisor is running.
- // (the result of the gethostname(2) system call)
- // If we are connected to a remote system,
- // then this returns the hostname of the remote system
- System.out.println("Host name: " + conn.getHostName());
- // Gets the name of the Hypervisor software used.
- System.out.println("Type: " + conn.getType());
- // Gets the version level of the Hypervisor running. This may work
- // only with hypervisor call, i.e. with priviledged access to the
- // hypervisor, not with a Read-Only connection. If the version can't
- // be extracted by lack of capacities returns 0.
- // Returns:
- // major * 1,000,000 + minor * 1,000 + release
- System.out.println(conn.getVersion());
- NodeInfo nodeInfo = conn.nodeInfo();
- System.out.println("the number of active CPUs: " + nodeInfo.cpus);
- System.out.println("number of core per socket: " + nodeInfo.cores);
- System.out.println("memory size in kilobytes: " + nodeInfo.memory);
- System.out.println("expected CPU frequency: " + nodeInfo.mhz);
- System.out.println("string indicating the CPU model: "
- + nodeInfo.model);
- System.out.println("the number of NUMA cell, 1 for uniform: "
- + nodeInfo.nodes);
- System.out.println("number of CPU socket per node: "
- + nodeInfo.sockets);
- System.out.println("number of threads per core: "
- + nodeInfo.threads);
- System.out
- .println("the total number of CPUs supported but not necessarily active in the host.: "
- + nodeInfo.maxCpus());
- // for (String interName : conn.listInterfaces()) {
- // System.out.println(interName);
- // } 不支持
- // Provides the list of names of defined interfaces on this host
- // for (String interName : conn.listDefinedInterfaces()) {
- // System.out.println(interName);
- // } // 不支持
- // Lists the active networks.
- for (String networkName : conn.listNetworks()) {
- System.out.println("Network name: " + networkName);
- }
- // Lists the names of the network filters
- for (String networkFilterName : conn.listNetworkFilters()) {
- System.out.println("Network filter name: " + networkFilterName);
- }
- System.out.println(conn.getCapabilities());
- } catch (LibvirtException e) {
- e.printStackTrace();
- }
- }
分別在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: numa:
gives similar information but when running a 32 bit OS fully virtualized with Xen using the hvm support。
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的個數,核心數,內存總量等直觀信息。有就足以。
看完了主機,再看看虛擬機。一個虛擬化環境中的核心資源自然是虛擬機,所以其屬性和信息也自然多很多,上測試代碼:
- /**
- * 測試探測虛擬機接口
- *
- * @author lihzh
- * @date 2012-5-16 上午11:14:20
- */
- @Test
- public void testDetectDomains() {
- // KVM
- doDetectDomains(kvmConn);
- // XEN
- doDetectDomains(xenConn);
- }
- /**
- * 執行探測虛擬機測試函數
- *
- * @param conn
- * @author lihzh
- * @date 2012-5-16 上午11:15:27
- */
- private void doDetectDomains(Connect conn) {
- try {
- // Lists the active domains.(列出所有處於啓動(激活)狀態的虛擬機的id)
- for (int activeDomId : conn.listDomains()) {
- System.out.println("Active vm id: " + activeDomId);
- // 根據Id,探測各個虛擬機的詳細信息
- Domain domain = conn.domainLookupByID(activeDomId);
- // Gets the hypervisor ID number for the domain
- System.out.println("Domain id: " + domain.getID());
- // Gets the public name for this domain
- System.out.println("Domain name: " + domain.getName());
- // Gets the type of domain operation system.
- System.out.println("Domain os type: " + domain.getOSType());
- // Gets the UUID for this domain as string.
- System.out.println("Domain uuid: " + domain.getUUIDString());
- // Retrieve the maximum amount of physical memory allocated to a
- // domain.
- System.out.println("Domain max memory: "
- + domain.getMaxMemory());
- // Provides the maximum number of virtual CPUs supported for the
- // guest VM. If the guest is inactive, this is basically the
- // same as virConnectGetMaxVcpus. If the guest is running this
- // will reflect the maximum number of virtual CPUs the guest was
- // booted with.
- System.out.println("Domain max vcpu: " + domain.getMaxVcpus());
- // Provides an XML description of the domain. The description
- // may be
- // reused later to relaunch the domain with createLinux().
- System.out.println("Domain xml description: "
- + domain.getXMLDesc(0));
- System.out.println("Domain maxMen allowed: "
- + domain.getInfo().maxMem);
- System.out.println("Domain memory: " + domain.getInfo().memory);
- // domain.getJobInfo()
- // 不支持
- System.out.println("Domain state: " + domain.getInfo().state);
- // Provides a boolean value indicating whether the network is
- // configured to be automatically started when the host machine
- // boots.
- System.out.println("Domain network autostart: "
- + domain.getAutostart());
- // Extracts information about virtual CPUs of this domain
- for (VcpuInfo vcpuInfo : domain.getVcpusInfo()) {
- System.out.println("cpu: " + vcpuInfo.cpu);
- System.out.println("cpu time: " + vcpuInfo.cpuTime);
- System.out.println("cpu number: " + vcpuInfo.number);
- System.out.println("cpu state: " + vcpuInfo.state);
- }
- // 如果是KVM環境
- if (conn.getURI().startsWith("qemu")) {
- // This function returns block device (disk) stats for block
- // devices attached to the domain
- DomainBlockInfo blockInfo = domain
- .blockInfo("/opt/awcloud/instance/admin/"
- + domain.getName() + "/disk");
- System.out.println("Disk Capacity: "
- + blockInfo.getCapacity());
- System.out.println("Disk allocation: "
- + blockInfo.getAllocation());
- System.out.println("Disk physical: "
- + blockInfo.getPhysical());
- DomainBlockStats blockStats = domain.blockStats("vda");
- // 磁盤讀取請求總數
- System.out.println("read request num: " + blockStats.rd_req);
- // 磁盤讀取總bytes數
- System.out.println("read request num: " + blockStats.rd_bytes);
- // 磁盤寫入請求總數
- System.out.println("read request num: " + blockStats.wr_req);
- // 磁盤寫入總bytes數
- System.out.println("read request num: " + blockStats.wr_bytes);
- }
- }
- // 列出所有停止態的虛擬機
- for (String name : conn.listDefinedDomains()) {
- System.out.println("Inactive domain name: " + name);
- }
- } catch (LibvirtException e) {
- e.printStackTrace();
- }
- }
循環較多,摘取部分結果如下:
Active vm id: 53Domain id: 53Domain name: i-546A099EDomain os type: hvmDomain uuid: e608560a-2c03-8e48-2e60-d0d01693f530Domain max memory: 147456Domain max vcpu: 1Domain 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: 147456Domain memory: 139140Domain state: VIR_DOMAIN_BLOCKEDDomain network autostart: falsecpu: 31cpu time: 2225977676675cpu number: 0cpu state: VIR_VCPU_BLOCKEDDomain network autostart: falseInactive domain name: i-46A70811Inactive domain name: i-38C20705Inactive domain name: i-498E09B2Inactive domain name: nullInactive domain name: nullInactive domain name: nullInactive domain name: nullInactive domain name: null
結果分析:
結果中基本包含了一個虛擬機組成的全部元素信息。如果你想做一個監控系統,你可以發現這裏有:
虛擬機的名字
虛擬機的Id
虛擬機的內存大小
虛擬CPU個數
虛擬機磁盤文件信息,磁盤文件的大小。甚至包括log等信息。
虛擬磁盤讀寫速率。
虛擬機網絡設備信息。Mac地址,設備類型等。
虛擬機網卡讀寫速率。
基本可以滿足一個監控系統的需求。
說明一下上面的測試代碼。libvirt Java API的入口基本都是通過Connect這個類,也就是首先建立與被管理主機之間的連接:
- Connect kvmConn = new Connect("qemu+tcp://10.4.54.10/system");
然後通過該連接獲取信息:
- conn.listDomains()
一個接口的如果需要接受參數:
- conn.domainLookupByID(activeDomId)
肯定可以從其他的接口返回中找到答案:
- for (int activeDomId : conn.listDomains())
只是有的獲取的直接,有可能需要解析xml格式的返回值來獲取需要參數值。比如:disk的paht和interface的path。
最後再簡單介紹一下管控接口:
- /**
- * 測試虛擬機的簡單操作
- *
- * @author lihzh
- * @date 2012-5-16 下午3:35:43
- */
- @Test
- public void testControlVM() {
- try {
- Domain domain = kvmConn.domainLookupByID(8);
- System.out.println("Domain state: " + domain.getInfo().state);
- domain.suspend();
- System.out.println("Domain state: " + domain.getInfo().state);
- for (int i = 0; i < 5; i++) {
- System.out.println("wait for: " + (5 - i));
- Thread.sleep(1000);
- }
- System.out.println("Resume vm.");
- domain.resume();
- System.out.println("Domain state: " + domain.getInfo().state);
- } catch (LibvirtException e) {
- e.printStackTrace();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
該用例主要測試了虛擬機的掛起和恢復操作。這類操作是比較簡單的(因爲無需參數)。一個複雜系統肯定需要包括虛擬機創建等操作。libvirt主要通過xml表述來創建資源,首先需要生成被創建虛擬機的完整描述,然後傳遞給創建的方法即可。描述的格式?呵呵,自然是上面測試結果給出的數據了。有興趣的,大家可以自己嘗試一下。libvirt的文檔,還不完善,不過對於創建這樣重要的功能,還是給出了說明。大家也可以下載官方的手冊作爲參考。
好了,相對於VMware、Xenserver等虛擬化平臺的SDK,libvirt的Java API還是比較簡單的,上手很快,結構很簡單。當然,功能上可能還是有所欠缺,信息量上,沒有其他的那麼充足。基於XML的方式操作資源,減少了接口的個數,使調用更直接,但是對開發人員卻增加了困難。不過仍不失爲一個不錯的虛擬機環境操作的API,尤其是針對KVM/XEN的環境來說,可謂不二的選擇。