<轉> Libvirt學習總結


感謝朋友支持本博客。歡迎共同探討交流。因為能力和時間有限,錯誤之處在所難免,歡迎指正!
假設轉載,請保留作者信息。
博客地址:http://blog.csdn.net/gaoxingnengjisuan
郵箱地址:dong.liu@siat.ac.cn


    這是本人之前在實驗室做的一個LIBVIRT學習報告。

1.什么是libvirt

    虛擬雲實現的三部曲:虛擬化技術實現-->虛擬機管理-->集群資源管理(雲管理)。各種不同的虛擬化技術都提供了主要的管理工具。

比方。啟動。停用,配置,連接控制台等。這樣在構建雲管理的時候就存在兩個問題:

    1) 假設採用混合虛擬技術,上層就須要對不同的虛擬化技術調用不同管理工具。非常是麻煩。

    2) 虛擬化技術發展非常迅速,系統虛擬化和容器虛擬化均在發展和演化中。可能有新的虛擬化技術更加符合如今的應用場景,須要遷移過去。這樣管理平台就須要大幅修改。
    為了適應變化,我們慣用的手段是分層。使之相互透明。在虛擬機和雲管理中設置一個抽象管理層。

libvirt就是扮演的這個角色。有了它,上面兩個問題就迎刃而解。

libvirt提供各種API,供上層來管理不同的虛擬機。


    Libvirt是管理虛擬機和其它虛擬化功能,比方存儲管理,網絡管理的軟件集合。它包含一個API庫,一個守護程序(libvirtd)和一個命令行工具(virsh)。libvirt本身構建於一種抽象的概念之上。

它為受支持的虛擬機監控程序實現的經常使用功能提供通用的API。

    libvirt的主要目標是為各種虛擬化工具提供一套方便、可靠的編程接口。用一種單一的方式管理多種不同的虛擬化提供方式。

2.Libvirt主要支持的功能
    虛擬機管理:包含不同的領域生命周期操作。比方:啟動、停止、暫停、保存、恢復和遷移。

支持多種設備類型的熱插拔操作,包含:磁盤、網卡、內存和CPU。
    遠程機器支持:
僅僅要機器上執行了libvirt daemon,包含遠程機器,全部的libvirt功能就都能夠訪問和使用。

支持多種網絡遠程傳輸。使用最簡單的SSH,不須要額外配置工作。
    存儲管理:
不論什么執行了libvirt daemon的主機都能夠用來管理不同類型的存儲:創建不同格式的文件鏡像(qcow2、vmdk、raw等)、掛接NFS共享、列出現有的LVM卷組、創建新的LVM卷組和邏輯卷、對未處理過的磁盤設備分區、掛接iSCSI共享。等等等等。由於libvirt能夠遠程工作。全部這些都能夠通過遠程主機使用。
    網絡接口管理:不論什么執行了libvirt daemon的主機都能夠用來管理物理和邏輯的網絡接口。
    虛擬NAT和基於路由的網絡:
不論什么執行了libvirt daemon的主機都能夠用來管理和創建虛擬網絡。



3.Libvirt語言綁定
    libvirt庫用C(支持 C++)實現。且包括對Python的直接支持。

只是它還支持大量語言綁定。眼下已經對Ruby、Java語言,Perl和 OCaml實施了綁定。libvirt支持最流行的系統編程語言(C和C++)、多種腳本語言。因此。無論您側重何種語言。都能夠方便的應用Libvirt。

4.Libvirt支持的虛擬機
    眼下支持的虛擬化技術包含:

    能夠說是很豐富,主流的虛擬化技術都包括了。

5.Libvirt
體系結構

    沒有使用libvirt的虛擬機管理方式例如以下圖所看到的:

    為支持各種虛擬機監控程序的可擴展性。libvirt實施一種基於驅動程序的架構,該架構同意一種通用的API以通用方式為大量潛在的虛擬機監控程序提供服務。下圖展示了libvirt API與相關驅動程序的層次結構。這里也須要注意,libvirtd提供從遠程應用程序訪問本地域的方式。

    libvirt的控制方式有兩種:
    1)管理應用程序和域位於同一節點上。管理應用程序通過libvirt工作,以控制本地域。

    2)管理應用程序和域位於不同節點上。該模式使用一種執行於遠程節點上、名為libvirtd的特殊守護進程。當在新節點上安裝libvirt時該程序會自己主動啟動,且可自己主動確定本地虛擬機監控程序並為其安裝驅動程序。

該管理應用程序通過一種通用協議從本地libvirt連接到遠程libvirtd。



6.Libvirt相關工具介紹
    接下來介紹一種名為virsh(虛擬 shell)的應用程序,基於命令行的管理工具。能夠實現簡單的資源管理。

它構建於libvirt之上,同意以交互方式使用多個libvirt功能。

    以下我們通過一個應用virsh來實現對域的管理的樣例來了解virsh這個工具:
    1).定義域配置文件。該代碼指定了定義域所需的全部選項—從虛擬機監控程序(仿真器)到域使用的資源以及外圍配置。

這僅僅是個簡單的配置。libvirt真正支持的屬性更加多樣化。


    2).完畢了域配置文件之后。使用virsh工具啟動域。

啟動新域時,使用create命令和域配置文件:

    ld@ld-Lenovo :~/libvtest$ virsh create react-qemu.xml
    Connecting to uri: qemu:///system
    Domain ReactOS-on-QEMU created from react-qemu.xml
    ld@ld-Lenovo :~/libvtest$
    3).使用virsh內的list命令列出給定主機上的活動域、域ID以及狀態:
    ld@ld-Lenovo :~/libvtest$ virsh list
    Connecting to uri: qemu:///system
    Id Name                 State
    ----------------------------------
    1 ReactOS-on-QEMU      running
    ld@ld-Lenovo :~/libvtest$
    4).也能夠使用suspend命令中止域。該命令可停止處於調度中的域,只是該域仍存在於內存中。可高速恢復執行。

    ld@ld-Lenovo :~/libvtest$ virsh suspend 1
    Connecting to uri: qemu:///system
    Domain 1 suspended
    ld@ld-Lenovo :~/libvtest$ virsh list
    Connecting to uri: qemu:///system
    Id Name                 State
    ----------------------------------
    1 ReactOS-on-QEMU      paused
    ld@ld-Lenovo :~/libvtest$ virsh resume 1
    Connecting to uri: qemu:///system
    Domain 1 resumed
    ld@ld-Lenovo :~/libvtest$

7.Libvirt和Pythonn
    Python是受libvirt支持的腳本語言,它向libvirt API提供全然面向對象的接口。

如今我們看一個使用Python來控制域的樣例。

    在本例中,從導入libvirt模塊開始。然后連接到本地虛擬機監控程序。

對每一個 ID 創建一個域對象,然后中止,繼續。最后刪除該域。

  1. import libvirt  
  2. conn = libvirt.open('qemu:///system')# 連接  
  3. for id in conn.listDomainsID():  
  4.     dom = conn.lookupByID(id)  
  5.     print "Dom %s State %s"%(dom.name(), dom.info()[0])  
  6.     dom.suspend()# 停止  
  7.     print "Dom %s State%s(after suspend)"%(dom.name(), dom.info()[0])  
  8.     dom.resume()# 繼續  
  9.     print "Dom %s State%s(after resume)"%(dom.name(), dom.info()[0])  
  10.     dom.destroy()# 刪除   
    輸出結果:
    ld@ld-Lenovo :~/libvtest$ python libvtest.py
    Dom ReactOS-on-QEMU  State 1
    Dom ReactOS-on-QEMU  State 3 (after suspend)
    Dom ReactOS-on-QEMU  State 1 (after resume)
    ld@ld-Lenovo :~/libvtest$
    盡管這僅僅是個簡單演示樣例,我們仍然可以看到 libvirt 通過 Python 提供的強大功能。通過一個簡單的腳本就行管理本地域。發行有關域的信息,然后控制域。

8.Libvirt API介紹
    高級libvirt API可划分為5個API部分:虛擬機監控程序連接API、域API、網絡API、存儲卷API、存儲池API。

1).連接API
    在libvirt中,連接是系統中的每個動作和對象的基礎。

每個實體,要與libvirt互相作用,應用virsh, virt-manager或者使用libvirt庫。都須要首先獲得一個到主機上libvirt守護進程的連接。

    鏈接是與特定的hypervisor相關聯的,它可能與libvirtclient程序同一時候執行在本地的一個節點上,也可能通過網絡連接到遠程的機器上。通常情況下,鏈接由virConnectPtr對象代表。而且由一個URI來定義。

    一個libvirt代理程序要做的第一件事就是調用libvirt連接函數獲得virConnectPtr句柄。在興許的操作中。該句柄作為全部其它管理功能的基礎。

(1).連接函數
    libvirt庫為連接到一個資源提供了三種不同的函數,三個函數之間的差別在於它們提供的驗證方式以及由此產生的授權的方法。
    virConnectPtr virConnectOpen(const char *name)
    以實現全然的讀寫訪問,不包括不論什么認證機制,而只提供一種連接。
    演示樣例:conn = virConnectOpen("qemu:///system");
    virConnectPtr virConnectOpenReadOnly(const char *name)
    virConnectOpenReadOnly API會打開一個僅僅讀訪問的連接。
    演示樣例:conn = virConnectOpenReadOnly("qemu:///system");
    virConnectPtr virConnectOpenAuth(const char *name, virConnectAuthPtr auth, int flags)
    提供了一種基於認證機制的連接;
    演示樣例:conn = virConnectOpenAuth("qemu+tcp://localhost/system", virConnectAuthPtrDefault, 0);
(2).關閉連接
    virConnectClose
    當不再須要連接的時候。必須調用virConnectClose來斷開連接。
    演示樣例:
    virConnectPtr conn;
    conn = virConnectOpen("qemu:///system");
    virConnectClose(conn);
(3).URI格式
    Libvirt使用統一的資源標識符(URI)來識別管理連接。

連接本地和遠程的hypervisor都是libvirt使用URI來進行處理。

    本地URI:
    Libvirt的本地URI具備下述格式之中的一個:
    driver:///system
    driver:///session
    driver+unix:///system
    driver+unix:///session
    遠程URI:
    遠程URI具有通用的格式("[...]"表示可選部分):
    driver[+transport]://[username@][hostname][:port]/[path][?extraparameters]
    參數解釋:
    driver:libvirt 所連接的driver的名字。

如xen, qemu,lxc, openvz和test。

    transport:傳輸數據方式。可用的方式包含tls, tcp, unix, ssh和ext。

    hostname:遠程機器的主機名。
    port:非常少使用。
    遠程訪問URI的樣例:
    應用SSH傳輸數據通道連接一個主機名為node.example.com上的遠程Xen hypervisor,SSH的username根文件夾為:xen+ssh://root@node.example.com/
(4).獲取虛擬機功能信息的API
    virConnectGetCapabilities的調用可以用於獲取虛擬主機的功能信息。

返回虛擬機監控程序和驅動程序的功能描寫敘述。它包括一個指針。假設調用成功,將返回一個字符串,當中包括了描寫敘述功能信息的XML文件。

    capabilities XML格式提供了有關主機虛擬化技術的信息。特別的,他描寫敘述了虛擬主機的功能、虛擬化驅動程序以及所採用的虛擬技術所可以啟動的client的類型等等。
    詳細樣例不再描寫敘述。
(5).獲取主機信息的API
    各種不同的API能夠用來獲得虛擬主機的信息,包含主機名、最大支持的CPU個數等。

    virConnectGetHostname的調用能夠獲得虛擬主機的主機名。
    virConnectGetMaxVcpus的調用能夠獲得每一個域的虛擬CPU最大個數。
    virNodeGetFreeMemory調用可以獲得虛擬主機中空暇內存的總量。
    virNodeGetInfo的調用能夠用來獲得虛擬主機的各種信息。

它採用了一個連接指針和一個virNodeInfo指針(由調用者分配)作為輸入,假設成功。則會返回0。而且將獲取信息填寫在virNodeInfo結構體中。

    virNodeInfo結構體包含下面成員:
    char model[32]                表示CPU型號的字符串
    unsigned long memory          以kb為單位的內存大小
    unsigned int cpus              活躍的CPU數目
    unsigned int mhz               期望的CPU頻率
    unsigned int nodes             NUMA節點數目。1表示一致性內存訪問
    unsigned int sockets           每個節點的CPU socket的數目
    unsigned int cores             每個socket的核數
    unsigned int threads           每個核的線程數
    virConnectGetType的調用可以獲得處於連接使用中的虛擬機的類型。
    virConnectGetVersion能夠獲取使用中的主機上虛擬機軟件的版本號。
    virConnectGetLibVersion能夠獲得正在使用中的主機上的libvirt軟件的版本號。
    virConnectGetURI可以用來獲取當前連接中的URI。
    virConnectIsEncrypted的調用可以查詢一個給定的連接是否加密。
    virConnectIsSecure的調用可以查詢一個給定的連接是否安全。
(6).錯誤處理API
    libvirt error API將會在一個正常的libvirt API調用返回錯誤標志的時候。

提供關於引發錯誤的很具體的信息。假設多個發生錯誤在沒有錯誤監測機制的連接上的時候。錯誤信息有可能會丟失。由於這個原因。強烈建議常常對錯誤進行監測,並在libvirt API調用失敗以后,馬上進行錯誤收集。


2).域API
    域API用於虛擬機管理,包含創建,啟動,停用,遷移。動態改動配置等。

    進入虛擬機監控程序后,便能夠使用一組 API 調用函數反復使用該虛擬機監控程序上的各種資源。API實現大量針對域的函數。要探究或管理域,首先須要一個virDomainPtr對象。您可通過多種方式獲得該句柄(使用ID、UUID或域名)。有了該域句柄,就能夠運行非常多操作。從探究域(virDomainGetUUID、virDomainGetInfo、virDomainGetXMLDesc)到控制域(virDomainCreate 、virDomainSuspend 、virDomainResume 、virDomainDestroy)。
    域能夠指不論什么正在執行的虛擬機或者是能夠用來啟動虛擬機的配置。鏈接對象提供了API用來枚舉域、創建新域和管理現有域。域用virDomainPtr對象來表示,並有自己唯一的標示符。
    域能夠是暫時的也能夠是持久的。

一個暫時的域僅僅由當它在主機上執行的時候才干夠被管理,一旦關閉。全部執行的跡象都會消失。

當一個持續的域被關閉時,仍然可能會管理這個域的無效的配置。當執行定義好的配置文件時。一個暫時的域能夠轉變成一個持續的域。

(1).域的標識符
    唯一標識符:
    ID:正整數類型。一個單節點上的若干域中,每一個域都有唯一的ID。無效的域沒有ID號。
    name:字符串類型,在一個主機上的全部域中是唯一的,包含執行的域和無效的域。

    UUID:16比特無符號類型。保證在不論什么主機上的全部域之間是唯一的。

(2).域的獲取
    有三個獲取現有的域的API,即virDomainLookupByID, virDomainLookupByName 和virDomainLookupByUUID.這些對象中都用一個連接對象作為第一個輸入參數,以及域標示符作為其他的輸入參數。


演示樣例:

    從ID獲取一個域對象
    int domainID = 6;
    virDomainPtr dom;
    dom = virDomainLookupByID(conn, domainID);
    從name獲取一個域對象
    int domainName = "someguest";
    virDomainPtr dom;
    dom = virDomainLookupByName(conn, domainName);
    從UUID獲取一個域對象
    char *domainUUID = "00311636-7767-71d2-e94a-26e7b8bad250";
    virDomainPtr dom;
    dom = virDomainLookupByUUIDString(conn, domainUUID);
(3).域表單的獲取
    Libvirt API公開了兩個域的列表,第一個包括執行域。第二個包括無效的持久的域。
    活躍的域列表的API--virConnectListDomains,返回域ID的列表。

為了確定ID數組的大小,應用程序能夠調用virConnectNumOfDomains API來解決。把這兩個API調用放在一起,打印執行域ID列表的代碼將會是例如以下所看到的:

  1. int i;  
  2. int numDomains;  
  3. int *activeDomains;  
  4. numDomains = virConnectNumOfDomains(conn);  
  5. activeDomains = malloc(sizeof(int) * numDomains);  
  6. numDomains = virConnectListDomains(conn, activeDomains, numDomains);  
  7. printf("Active domain IDs:\n");  
  8. for (i = 0 ; i < numDomains ; i++) {  
  9.     printf(" %d\n", activeDomains[i]);  
  10. }  
  11. free(activeDomains);  
    除了正在執行的域。可能還會有一些持久的無效域配置存儲在主機上。假設一個無效的域不具備不論什么的ID標志,這個不活躍域的列表將會以name字符串列表的形式輸出。

    virConnectListDefinedDomains將會返回所填充的name字符串到數組元素的總數量。也有一個virConnectNumOfDefinedDomains來確定name的數量。

打印無效的持久域的name列表的代碼將會是例如以下所看到的:

  1. int i;  
  2. int numDomains;  
  3. char **inactiveDomains;  
  4. numDomains = virConnectNumOfDefinedDomains(conn);  
  5. inactiveDomains = malloc(sizeof(char *) * numDomains);  
  6. numDomains = virConnectListDomains(conn, inactiveDomains, numDomains);  
  7. printf("Inactive domain names:\n");  
  8. for (i = 0 ; i < numDomains ; i++) {  
  9.     printf(" %s\n", inactiveDomains[i]);  
  10.     free(inactiveDomains[i]);  
  11. }  
  12. free(inactiveDomains);  
(4).域生命周期的控制
    Libvirt可以控制域的整個生命周期。域可以在它的整個生命周期的幾個狀態之間進行轉換:
    Undefined這是一個主要的狀態。

不論什么未定義或者沒有建立的域的狀態。

    Defined這是一個域已定義可是沒有執行的狀態。這樣的狀態也能夠被描寫敘述為停止。
    Running這是一個已經定義並執行在一個hypervisor上面的域的狀態。
    Paused這個狀態是形容一個域系統從執行狀態轉換為暫停狀態。它的內存鏡像已經被臨時地存儲。它能夠恢復到執行狀態。


    三個重要的API:
    virDomainCreateXML將會建立並馬上引導啟動一個新的暫時性的域。

當這個域系統關閉的時候。全部的執行痕跡將會消失。

    virDomainDefineXML將會為一個持久性的域建立並存儲配置文件。

    virDomainCreate將會從持久性配置中引導啟動一個預先定義的域。
    引導一個暫時的域
    假設想引導一個暫時的域。僅僅須要建立一個對libvirt的連接以及一個包括了描寫敘述了所需求的域的配置的XML文檔的字符串。
  1. virDomainPtr dom;  
  2. const char *xmlconfig = "<domain>........</domain>";  
  3. dom = virConnectCreateXML(conn, xmlconfig, 0);  
  4. if (!dom)   
  5. {      
  6.     fprintf(stderr, "Domain creation failed");      
  7.     return;  
  8. }  
  9. fprintf(stderr, "Guest %s has booted",virDomainName(dom));  
  10. virDomainFree(dom);   
    假設創建域的嘗試成功,那么將會返回virDomainPtr作為這個域的句柄。雖然域引導啟動成功。可是這不能保證這個域的持續執行。


    定義並引導一個持久的域
    在一個持久域可以被引導之前,必須使它的配置文件已經定義完畢。這也要求建立一個對libvirt的連接以及一個包括了描寫敘述了所需求的來賓域的配置文件的XML文檔的字符串。以下的演示樣例假定了conn是virConnectPtr對象的實例。


  1. virDomainPtr dom;  
  2. const char *xmlconfig = "<domain>........</domain>";  
  3. dom = virConnectDefineXML(conn, xmlconfig, 0);  
  4. if(virDomainCreate(dom) < 0){      
  5.     virDomainFree(dom);      
  6.     fprintf(stderr, "Cannot boot guest");      
  7.     return;  
  8. }  
  9. fprintf(stderr,"Guest %s has booted",virDomainName(dom));  
  10. virDomainFree(dom);  

    至於網絡 API(監控虛擬網絡)、存儲卷 API(管理存儲設備)和存儲池 API(管理存儲文件系統)這里先不做介紹了。假設有須要的話,能夠直接看官方文檔,介紹的非常具體,還有非常多簡單明了的演示樣例。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM