Libvirt学习总结
這是本人之前在實驗室做的一個LIBVIRT學(xué)習(xí)報告。
1.什么是libvirt
??? 虛擬云實現(xiàn)的三部曲:虛擬化技術(shù)實現(xiàn)-->虛擬機管理-->集群資源管理(云管理)。各種不同的虛擬化技術(shù)都提供了基本的管理工具。比如,啟動,停用,配置,連接控制臺等。這樣在構(gòu)建云管理的時候就存在兩個問題:
??? 1) 如果采用混合虛擬技術(shù),上層就需要對不同的虛擬化技術(shù)調(diào)用不同管理工具,很是麻煩。
??? 2) 虛擬化技術(shù)發(fā)展很迅速,系統(tǒng)虛擬化和容器虛擬化均在發(fā)展和演化中。可能有新的虛擬化技術(shù)更加符合現(xiàn)在的應(yīng)用場景,需要遷移過去。這樣管理平臺就需要大幅改動。
??? 為了適應(yīng)變化,我們慣用的手段是分層,使之相互透明,在虛擬機和云管理中設(shè)置一個抽象管理層。libvirt就是扮演的這個角色。有了它,上面兩個問題就迎刃而解。libvirt提供各種API,供上層來管理不同的虛擬機。
??? Libvirt是管理虛擬機和其他虛擬化功能,比如存儲管理,網(wǎng)絡(luò)管理的軟件集合。它包括一個API庫,一個守護程序(libvirtd)和一個命令行工具(virsh);libvirt本身構(gòu)建于一種抽象的概念之上。它為受支持的虛擬機監(jiān)控程序?qū)崿F(xiàn)的常用功能提供通用的API。
??? libvirt的主要目標(biāo)是為各種虛擬化工具提供一套方便、可靠的編程接口,用一種單一的方式管理多種不同的虛擬化提供方式。
?
2.Libvirt主要支持的功能
??? 虛擬機管理:包括不同的領(lǐng)域生命周期操作,比如:啟動、停止、暫停、保存、恢復(fù)和遷移。支持多種設(shè)備類型的熱插拔操作,包括:磁盤、網(wǎng)卡、內(nèi)存和CPU。
??? 遠程機器支持:只要機器上運行了libvirt daemon,包括遠程機器,所有的libvirt功能就都可以訪問和使用。支持多種網(wǎng)絡(luò)遠程傳輸,使用最簡單的SSH,不需要額外配置工作。
??? 存儲管理:任何運行了libvirt daemon的主機都可以用來管理不同類型的存儲:創(chuàng)建不同格式的文件鏡像(qcow2、vmdk、raw等)、掛接NFS共享、列出現(xiàn)有的LVM卷組、創(chuàng)建新的LVM卷組和邏輯卷、對未處理過的磁盤設(shè)備分區(qū)、掛接iSCSI共享,等等等等。因為libvirt可以遠程工作,所有這些都可以通過遠程主機使用。
??? 網(wǎng)絡(luò)接口管理:任何運行了libvirt daemon的主機都可以用來管理物理和邏輯的網(wǎng)絡(luò)接口。
??? 虛擬NAT和基于路由的網(wǎng)絡(luò):任何運行了libvirt daemon的主機都可以用來管理和創(chuàng)建虛擬網(wǎng)絡(luò)。
?
3.Libvirt語言綁定
??? libvirt庫用C(支持 C++)實現(xiàn),且包含對Python的直?接支持。不過它還支持大量語言綁定。目前已經(jīng)對Ruby?、Java語言,Perl和 OCaml實施了綁定。libvirt支持最?流行的系統(tǒng)編程語言(C和C++)、多種腳本語言。因此?,不管您側(cè)重何種語言,都可以方便的應(yīng)用Libvirt。
4.Libvirt支持的虛擬機
??? 目前支持的虛擬化技術(shù)包括:
??? 可以說是非常豐富,主流的虛擬化技術(shù)都包含了。
5.Libvirt?體系結(jié)構(gòu)
??? 沒有使用libvirt的虛擬機管理方式如下圖所示:
??? 為支持各種虛擬機監(jiān)控程序的可擴展性,libvirt實施一種基于驅(qū)動程序的架構(gòu),該架構(gòu)允許一種通用的API以通用方式為大量潛在的虛擬機監(jiān)控程序提供服務(wù)。下圖展示了libvirt API與相關(guān)驅(qū)動程序的層次結(jié)構(gòu)。這里也需要注意,libvirtd提供從遠程應(yīng)用程序訪問本地域的方式。
??? libvirt的控制方式有兩種:
??? 1)管理應(yīng)用程序和域位于同一節(jié)點上。管理應(yīng)用程序通過libvirt工作,以控制本地域。
??? 2)管理應(yīng)用程序和域位于不同節(jié)點上。該模式使用一種運行于遠程節(jié)點上、名為libvirtd的特殊守護進程。當(dāng)在新節(jié)點上安裝libvirt時該程序會自動啟動,且可自動確定本地虛擬機監(jiān)控程序并為其安裝驅(qū)動程序。該管理應(yīng)用程序通過一種通用協(xié)議從本地libvirt連接到遠程libvirtd。
6.Libvirt相關(guān)工具介紹
??? 接下來介紹一種名為virsh(虛擬 shell)的應(yīng)用程序,基于命令行的管理工具,可以實現(xiàn)簡單的資源管理。它構(gòu)建于libvirt之上,允許以交互方式使用多個libvirt功能。
??? 下面我們通過一個應(yīng)用virsh來實現(xiàn)對域的管理的例子來了解virsh這個工具:
??? 1).定義域配置文件。該代碼指定了定義域所需的所有選項—從虛擬機監(jiān)控程序(仿真器)到域使用的資源以及外圍配置。這只是個簡單的配置,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內(nèi)的list命令列出給定主機上的活動域、域ID以及狀態(tài):
??? 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命令中止域。該命令可停止處于調(diào)度中的域,不過該域仍存在于內(nèi)存中,可快速恢復(fù)運行。
??? 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提供完全面向?qū)ο蟮慕涌凇,F(xiàn)在我們看一個使用Python來控制域的例子。
??? 在本例中,從導(dǎo)入libvirt模塊開始。然后連接到本地虛擬機監(jiān)控程序。對每個 ID 創(chuàng)建一個域?qū)ο?#xff0c;然后中止,繼續(xù),最后刪除該域。
?import libvirt
conn = libvirt.open('qemu:///system')# 連接
for id in conn.listDomainsID():
dom = conn.lookupByID(id)
print "Dom %s State %s"%(dom.name(), dom.info()[0])
dom.suspend()# 停止
print "Dom %s State%s(after suspend)"%(dom.name(), dom.info()[0])
dom.resume()# 繼續(xù)
print "Dom %s State%s(after resume)"%(dom.name(), dom.info()[0])
dom.destroy()# 刪除
??? 輸出結(jié)果:
??? 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$
??? 雖然這只是個簡單示例,我們?nèi)匀豢梢钥吹?libvirt 通過 Python 提供的強大功能。通過一個簡單的腳本就能夠管理本地域,發(fā)行有關(guān)域的信息,然后控制域。
?
8.Libvirt API介紹
??? 高級libvirt API可劃分為5個API部分:虛擬機監(jiān)控程序連接API、域API、網(wǎng)絡(luò)API、存儲卷API、存儲池API。
?
1).連接API
??? 在libvirt中,連接是系統(tǒng)中的每一個動作和對象的基礎(chǔ)。每一個實體,要與libvirt互相作用,應(yīng)用virsh, virt-manager或者使用libvirt庫,都需要首先獲得一個到主機上libvirt守護進程的連接。
??? 鏈接是與特定的hypervisor相關(guān)聯(lián)的,它可能與libvirt客戶端程序同時運行在本地的一個節(jié)點上,也可能通過網(wǎng)絡(luò)連接到遠程的機器上。通常情況下,鏈接由virConnectPtr對象代表,并且由一個URI來定義。
??? 一個libvirt代理程序要做的第一件事就是調(diào)用libvirt連接函數(shù)獲得virConnectPtr句柄。在后續(xù)的操作中,該句柄作為所有其他管理功能的基礎(chǔ)。
(1).連接函數(shù)
??? libvirt庫為連接到一個資源提供了三種不同的函數(shù),三個函數(shù)之間的區(qū)別在于它們提供的驗證方式以及由此產(chǎn)生的授權(quán)的方法。
??? virConnectPtr virConnectOpen(const char *name)
??? 以實現(xiàn)完全的讀寫訪問,不包含任何認證機制,而僅僅提供一種連接。
??? 示例: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).關(guān)閉連接
??? virConnectClose
??? 當(dāng)不再需要連接的時候,必須調(diào)用virConnectClose來斷開連接。
??? 示例:
??? virConnectPtr conn;
??? conn = virConnectOpen("qemu:///system");
??? virConnectClose(conn);
(3).URI格式
??? Libvirt使用統(tǒng)一的資源標(biāo)識符(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]
??? 參數(shù)解釋:
??? driver:libvirt 所連接的driver的名字。如xen, qemu,lxc, openvz和test。
??? transport:數(shù)據(jù)傳輸方式,可用的方式包括tls, tcp, unix, ssh和ext。
??? hostname:遠程機器的主機名。
??? port:很少使用。
??? 遠程訪問URI的例子:
??? 應(yīng)用SSH數(shù)據(jù)傳輸通道連接一個主機名為node.example.com上的遠程Xen hypervisor,SSH的用戶名根目錄為:xen+ssh://root@node.example.com/
(4).獲取虛擬機功能信息的API
??? virConnectGetCapabilities的調(diào)用能夠用于獲取虛擬主機的功能信息。返回虛擬機監(jiān)控程序和驅(qū)動程序的功能描述。它包含一個指針,如果調(diào)用成功,將返回一個字符串,其中包括了描述功能信息的XML文件。
??? capabilities XML格式提供了有關(guān)主機虛擬化技術(shù)的信息。特別的,他描述了虛擬主機的功能、虛擬化驅(qū)動程序以及所采用的虛擬技術(shù)所能夠啟動的客戶端的類型等等。
??? 具體例子不再描述。
(5).獲取主機信息的API
??? 各種不同的API可以用來獲得虛擬主機的信息,包括主機名、最大支持的CPU個數(shù)等。
??? virConnectGetHostname的調(diào)用可以獲得虛擬主機的主機名。
??? virConnectGetMaxVcpus的調(diào)用可以獲得每個域的虛擬CPU最大個數(shù)。
??? virNodeGetFreeMemory調(diào)用能夠獲得虛擬主機中空閑內(nèi)存的總量。
??? virNodeGetInfo的調(diào)用可以用來獲得虛擬主機的各種信息。它采用了一個連接指針和一個virNodeInfo指針(由調(diào)用者分配)作為輸入,如果成功,則會返回0,并且將獲取信息填寫在virNodeInfo結(jié)構(gòu)體中。
??? virNodeInfo結(jié)構(gòu)體包括以下成員:
??? char model[32]??????????????? 表示CPU型號的字符串
??? unsigned long memory????????? 以kb為單位的內(nèi)存大小
??? unsigned int cpus????????????? 活躍的CPU數(shù)目
??? unsigned int mhz?????????????? 期望的CPU頻率
??? unsigned int nodes???????????? NUMA節(jié)點數(shù)目,1表示一致性內(nèi)存訪問
??? unsigned int sockets?????????? 每一個節(jié)點的CPU socket的數(shù)目
??? unsigned int cores???????????? 每一個socket的核數(shù)
??? unsigned int threads?????????? 每一個核的線程數(shù)
??? virConnectGetType的調(diào)用能夠獲得處于連接使用中的虛擬機的類型。
??? virConnectGetVersion可以獲取使用中的主機上虛擬機軟件的版本。
??? virConnectGetLibVersion可以獲得正在使用中的主機上的libvirt軟件的版本。
??? virConnectGetURI能夠用來獲取當(dāng)前連接中的URI。
??? virConnectIsEncrypted的調(diào)用能夠查詢一個給定的連接是否加密。
??? virConnectIsSecure的調(diào)用能夠查詢一個給定的連接是否安全。
(6).錯誤處理API
??? libvirt error API將會在一個正常的libvirt API調(diào)用返回錯誤標(biāo)志的時候。提供關(guān)于引發(fā)錯誤的非常詳細的信息。如果多個錯誤發(fā)生在沒有錯誤監(jiān)測機制的連接上的時候,錯誤信息有可能會丟失。因為這個原因,強烈建議經(jīng)常對錯誤進行監(jiān)測,并在libvirt API調(diào)用失敗以后,立即進行錯誤收集。
?
2).域API
??? 域API用于虛擬機管理,包括創(chuàng)建,啟動,停用,遷移,動態(tài)修改配置等。
??? 進入虛擬機監(jiān)控程序后,便可以使用一組 API 調(diào)用函數(shù)重復(fù)使用該虛擬機監(jiān)控程序上的各種資源。API實現(xiàn)大量針對域的函數(shù)。要探究或管理域,首先需要一個virDomainPtr對象。您可通過多種方式獲得該句柄(使用ID、UUID或域名)。有了該域句柄,就可以執(zhí)行很多操作,從探究域(virDomainGetUUID、virDomainGetInfo、virDomainGetXMLDesc)到控制域(virDomainCreate 、virDomainSuspend 、virDomainResume 、virDomainDestroy)。
??? 域可以指任何正在運行的虛擬機或者是可以用來啟動虛擬機的配置。鏈接對象提供了API用來枚舉域、創(chuàng)建新域和管理現(xiàn)有域。域用virDomainPtr對象來表示,并有自己唯一的標(biāo)示符。
??? 域可以是臨時的也可以是持久的。一個臨時的域只由當(dāng)它在主機上運行的時候才能夠被管理,一旦關(guān)閉,所有運行的跡象都會消失。當(dāng)一個持續(xù)的域被關(guān)閉時,仍然可能會管理這個域的無效的配置。當(dāng)運行定義好的配置文件時,一個臨時的域可以轉(zhuǎn)變成一個持續(xù)的域。
(1).域的標(biāo)識符
??? 唯一標(biāo)識符:
??? ID:正整數(shù)類型,一個單節(jié)點上的若干域中,每個域都有唯一的ID。無效的域沒有ID號。
??? name:字符串類型,在一個主機上的所有域中是唯一的,包括運行的域和無效的域。
??? UUID:16比特?zé)o符號類型,保證在任何主機上的所有域之間是唯一的。
(2).域的獲取
??? 有三個獲取現(xiàn)有的域的API,即virDomainLookupByID, virDomainLookupByName 和virDomainLookupByUUID.這些對象中都用一個連接對象作為第一個輸入?yún)?shù),以及域標(biāo)示符作為其它的輸入?yún)?shù)。
示例:
??? 從ID獲取一個域?qū)ο?/strong>
??? int domainID = 6;
??? virDomainPtr dom;
??? dom = virDomainLookupByID(conn, domainID);
??? 從name獲取一個域?qū)ο?/strong>
??? int domainName = "someguest";
??? virDomainPtr dom;
??? dom = virDomainLookupByName(conn, domainName);
??? 從UUID獲取一個域?qū)ο?/strong>
??? char *domainUUID = "00311636-7767-71d2-e94a-26e7b8bad250";
??? virDomainPtr dom;
??? dom = virDomainLookupByUUIDString(conn, domainUUID);
(3).域表單的獲取
??? Libvirt API公開了兩個域的列表,第一個包含運行域,第二個包含無效的持久的域。
??? 活躍的域列表的API--virConnectListDomains,返回域ID的列表。為了確定ID數(shù)組的大小,應(yīng)用程序可以調(diào)用virConnectNumOfDomains API來解決。把這兩個API調(diào)用放在一起,打印運行域ID列表的代碼將會是如下所示:
?int i;
int numDomains;
int *activeDomains;
numDomains = virConnectNumOfDomains(conn);
activeDomains = malloc(sizeof(int) * numDomains);
numDomains = virConnectListDomains(conn, activeDomains, numDomains);
printf("Active domain IDs:\n");
for (i = 0 ; i < numDomains ; i++) {
printf(" %d\n", activeDomains[i]);
}
free(activeDomains);
??? 除了正在運行的域,可能還會有一些持久的無效域配置存儲在主機上。如果一個無效的域不具備任何的ID標(biāo)志,這個不活躍域的列表將會以name字符串列表的形式輸出。??? virConnectListDefinedDomains將會返回所填充的name字符串到數(shù)組元素的總數(shù)量。也有一個virConnectNumOfDefinedDomains來確定name的數(shù)量。打印無效的持久域的name列表的代碼將會是如下所示:
?int i;
int numDomains;
char **inactiveDomains;
numDomains = virConnectNumOfDefinedDomains(conn);
inactiveDomains = malloc(sizeof(char *) * numDomains);
numDomains = virConnectListDomains(conn, inactiveDomains, numDomains);
printf("Inactive domain names:\n");
for (i = 0 ; i < numDomains ; i++) {
printf(" %s\n", inactiveDomains[i]);
free(inactiveDomains[i]);
}
free(inactiveDomains);
(4).域生命周期的控制
??? Libvirt能夠控制域的整個生命周期。域可以在它的整個生命周期的幾個狀態(tài)之間進行轉(zhuǎn)換:
??? Undefined這是一個基本的狀態(tài)。任何沒有定義或者沒有建立的域的狀態(tài)。
??? Defined這是一個域已定義但是沒有運行的狀態(tài)。這種狀態(tài)也可以被描述為停止。
??? Running這是一個已經(jīng)定義并運行在一個hypervisor上面的域的狀態(tài)。
??? Paused這個狀態(tài)是形容一個域系統(tǒng)從運行狀態(tài)轉(zhuǎn)換為暫停狀態(tài)。它的內(nèi)存鏡像已經(jīng)被暫時地存儲,它可以恢復(fù)到運行狀態(tài)。
??? 三個重要的API:
??? virDomainCreateXML將會建立并立即引導(dǎo)啟動一個新的臨時性的域。當(dāng)這個域系統(tǒng)關(guān)閉的時候,所有的運行痕跡將會消失。
??? virDomainDefineXML將會為一個持久性的域建立并存儲配置文件。
??? virDomainCreate將會從持久性配置中引導(dǎo)啟動一個預(yù)先定義的域。
??? 引導(dǎo)一個臨時的域
??? 如果想引導(dǎo)一個臨時的域,只需要建立一個對libvirt的連接以及一個包含了描述了所需求的域的配置的XML文檔的字符串。
?virDomainPtr dom;
const char *xmlconfig = "<domain>........</domain>";
dom = virConnectCreateXML(conn, xmlconfig, 0);
if (!dom)
{
fprintf(stderr, "Domain creation failed");
return;
}
fprintf(stderr, "Guest %s has booted",virDomainName(dom));
virDomainFree(dom);
??? 如果創(chuàng)建域的嘗試成功,那么將會返回virDomainPtr作為這個域的句柄。盡管域引導(dǎo)啟動成功,但是這不能保證這個域的持續(xù)運行。
??? 定義并引導(dǎo)一個持久的域
??? 在一個持久域能夠被引導(dǎo)之前,必須使它的配置文件已經(jīng)定義完成。這也要求建立一個對libvirt的連接以及一個包含了描述了所需求的來賓域的配置文件的XML文檔的字符串。下面的示例假定了conn是virConnectPtr對象的實例。
?virDomainPtr dom;
const char *xmlconfig = "<domain>........</domain>";
dom = virConnectDefineXML(conn, xmlconfig, 0);
if(virDomainCreate(dom) < 0){
virDomainFree(dom);
fprintf(stderr, "Cannot boot guest");
return;
}
fprintf(stderr,"Guest %s has booted",virDomainName(dom));
virDomainFree(dom);
??? 至于網(wǎng)絡(luò) API(監(jiān)控虛擬網(wǎng)絡(luò))、存儲卷 API(管理存儲設(shè)備)和存儲池 API(管理存儲文件系統(tǒng))這里先不做介紹了,如果有需要的話,可以直接看官方文檔,介紹的很詳細,還有很多簡單明了的示例。
總結(jié)
以上是生活随笔為你收集整理的Libvirt学习总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux操作系统相关资料
- 下一篇: flow_from_directory返