天天看點

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

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

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

libvirt的管理機關是單個主機,是以探測和監控接口所能擷取的資訊的最大範圍也是主機。是以先從主機入手,驗證libvirt接口。主機(libvirt所在管理節點)探測相關接口驗證代碼如下:

@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 

     * @date 2012-5-15 下午1:37:37 

    private void doDetectHost(Connect conn) { 

            // 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()) { 

            // } // 不支援 

            // 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()); 

 分别在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>

    </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

memory size in kilobytes: 50276352

expected CPU frequency: 1995

number of CPU socket per node: 2

the total number of CPUs supported but not necessarily active in the host.: 32

Network filter name: allow-dhcp-server

Network filter name: qemu-announce-self-rarp

      <features>

        <vmx/>

      </features>

        <uri_transport>xenmigr</uri_transport>

    <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'>

  ... 

說明:

注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的個數,核心數,記憶體總量等直覺資訊。有就足以。

看完了主機,再看看虛拟機。一個虛拟化環境中的核心資源自然是虛拟機,是以其屬性和資訊也自然多很多,上測試代碼:

/**  

     * 測試探測虛拟機接口  

     *   

     * @author lihzh  

     * @date 2012-5-16 上午11:14:20  

    public void testDetectDomains() {  

        // KVM  

        doDetectDomains(kvmConn);  

        // XEN  

        doDetectDomains(xenConn);  

    }  

     * 執行探測虛拟機測試函數  

     * @param conn  

     * @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: 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>

      <source file='/opt/awcloud/instance/admin/i-546A099E/disk2'/>

      <target dev='hdb' bus='ide'/>

    <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'>

    </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

Inactive domain name: i-46A70811

Inactive domain name: i-38C20705

Inactive domain name: i-498E09B2

Inactive 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。

最後再簡單介紹一下管控接口:

     * 測試虛拟機的簡單操作  

     * @date 2012-5-16 下午3:35:43  

    public void testControlVM() {  

            Domain domain = kvmConn.domainLookupByID(8);  

            System.out.println("Domain state: " + domain.getInfo().state);  

            domain.suspend();  

            for (int i = 0; i < 5; i++) {  

                System.out.println("wait for: " + (5 - i));  

                Thread.sleep(1000);  

            System.out.println("Resume vm.");  

            domain.resume();  

        } catch (InterruptedException e) {  

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

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

     本文轉自mushiqianmeng 51CTO部落格,原文連結:http://blog.51cto.com/mushiqianmeng/865174,如需轉載請自行聯系原作者