libvirt

出自 Arch Linux 中文维基

Libvirt 是一組軟件的匯集,提供了管理虛擬機和其它虛擬化功能(如:存儲和網絡接口等)的便利途徑。這些軟件包括:一個長期穩定的 C 語言 API、一個守護進程(libvirtd)和一個命令行工具(virsh)。Libvirt 的主要目標是提供一個單一途徑以管理多種不同虛擬化方案以及虛擬化主機,包括:KVM/QEMUXenLXCOpenVZVirtualBox hypervisors詳見這裡)。

Libvirt 的一些主要功能如下:

  • VM management(虛擬機管理):各種虛擬機生命周期的操作,如:啟動、停止、暫停、保存、恢復和遷移等;多種不同類型設備的熱插拔操作,包括磁盤、網絡接口、內存、CPU等。
  • Remote machine support(支持遠程連接):Libvirt 的所有功能都可以在運行着 libvirt 守護進程的機器上執行,包括遠程機器。可以使用最簡便且無需額外配置的 SSH 協議,也可以使用受支持的多種網絡連接方式。
  • Storage management(存儲管理):任何運行 libvirt 守護進程的主機都可以用於管理多種類型的存儲:創建多種類型的文件鏡像(qcow2,vmdk,raw,...),掛載 NFS 共享,枚舉現有 LVM 卷組,創建新的 LVM 卷組和邏輯卷,對裸磁盤設備分區,掛載 iSCSI 共享,以及更多......
  • Network interface management(網絡接口管理):任何運行 libvirt 守護進程的主機都可以用於管理物理的和邏輯的網絡接口,枚舉現有接口,配置(和創建)接口、橋接、VLAN、端口綁定。
  • Virtual NAT and Route based networking(虛擬 NAT 和基於路由的網絡):任何運行 libvirt 守護進程的主機都可以管理和創建虛擬網絡。Libvirt 虛擬網絡使用防火牆規則實現一個路由器,為虛擬機提供到主機網絡的透明訪問。

安裝[編輯 | 編輯原始碼]

基於守護進程/客戶端的架構的 libvirt 只需要安裝在需要要實現虛擬化的機器上。注意,服務器和客戶端可以是相同的物理機器。

服務端[編輯 | 編輯原始碼]

安裝 libvirt 以及至少一個虛擬運行環境(hypervisor):

  • 其他受支持的虛擬運行環境包括 LXCVirtualBoxXen。請參見它們各自的安裝說明。有關 libvirtd 的安裝備註:
    • Libvirt 的 LXC 驅動 並不依賴 lxc 提供的 LXC 用戶空間工具。因此,無需安裝該工具也能使用這個驅動。需要 libvirtd 處於運行狀態才能使用 libvirt-lxc 連接。
    • Libvirt 能支持 Xen,但默認未內建支持(FS#27356)。需要用 ABS 編輯 libvirtPKGBUILD ,去掉 -Ddriver_libxl=disabled 選項後重新構建(built)libvirt。

對於網絡連接,需要安裝這些包:

Other optional dependencies may provide desired or extended features, such as dmidecode for DMI system info support. Install the ones you may need as dependencies after reading pacman's output for libvirt.

注意: If you are using firewalld, as of libvirt 5.1.0 and firewalld 0.7.0 you no longer need to change the firewall backend to iptables. libvirt now installs a zone called 'libvirt' in firewalld and manages its required network rules there. See Firewall and network filtering in libvirt.

客戶端[編輯 | 編輯原始碼]

客戶端是用於管理和訪問虛擬機的用戶界面。

  • virsh — 用於管理和配置域(虛擬機)的命令行程序。
https://libvirt.org/ || libvirt
  • GNOME Boxes — 簡單的 GNOME 3 程序,可以訪問遠程虛擬系統。是 gnome-extra包組的一部分。
https://wiki.gnome.org/Apps/Boxes || gnome-boxes
  • Libvirt Sandbox — 應用程序沙箱工具包。
https://sandbox.libvirt.org/ || libvirt-sandboxAUR
  • Virt Viewer — 簡單的遠程顯示客戶端。
https://gitlab.com/virt-viewer/virt-viewer || virt-viewer
  • Qt VirtManager — 管理虛擬機的Qt程序。
https://github.com/F1ash/qt-virt-manager || qt-virt-managerAUR
  • Virt-manager — 用於圖形化使用 libvirt 管理 KVM,Xen 或是 LXC。
https://virt-manager.org/ || virt-manager
  • Cockpit — 基於網頁的系統管理工具,可通過插件管理虛擬機。
https://cockpit-project.org/ || cockpit-machines

兼容 libvirt 的軟件列表見 這裡.

配置[編輯 | 編輯原始碼]

對於系統 級別的管理任務(如:全局配置和鏡像 位置),libvirt 要求至少要設置授權啟動守護進程

注意: 對於用戶會話 級別的管理任務,守護進程的安裝和設置不是必須的。授權總是僅限本地,前台程序將啟動一個 libvirtd 守護進程的本地實例。

設置授權[編輯 | 編輯原始碼]

來自 libvirt:連接授權

Libvirt 守護進程允許管理員分別為客戶端連接的每個網絡 socket 選擇不同授權機制。這主要是通過 libvirt 守護進程的主配置文件 /etc/libvirt/libvirtd.conf 來實現的。每個 libvirt socket 可以有獨立的授權機制配置。目前的可選項有 nonepolkitsasl

Using libvirt group[編輯 | 編輯原始碼]

The easiest way to ensure your user has access to libvirt daemon is to add member to libvirt user group.

Members of the libvirt group have passwordless access to the RW daemon socket by default.

使用 polkit[編輯 | 編輯原始碼]

Because libvirt pulls polkit as a dependency during installation, polkit is used as the default value for the unix_sock_auth parameter (source). File-based permissions remain nevertheless available.

注意: 為使 polkit 認證工作正常,應該重啟一次系統。

libvirt 守護進程在 polkit 策略配置文件(/usr/share/polkit-1/actions/org.libvirt.unix.policy)中提供了兩種 polkit 操作

  • org.libvirt.unix.manage 面向完全的管理訪問(讀寫模式後台 socket),以及
  • org.libvirt.unix.monitor 面向僅監視察看訪問(只讀 socket)。

默認的面向讀寫模式後台 socket 的策略需要認證為管理員。這點類似於 sudo 認證,但它並不要求客戶應用最終以 root 身份運行。默認策略下也仍然允許任何應用連接到只讀 socket。

Arch Linux 默認 wheel 組的所有用戶都是管理員身份:定義於 /etc/polkit-1/rules.d/50-default.rules(參閱:Polkit#管理員身份認證)。所以如果用戶是 wheel 組的成員,就不必新建組和規則文件:只要連接到了讀寫模式 socket(例如通過 virt-manager)就會被提示輸入該用戶的口令。

注意: 口令提示依賴於系統上的身份認證組件。文本控制台默認的認證代理是 pkttyagent,它可能因工作不正常而導致各種問題。
提示:如果要配置無口令認證,參閱 Polkit#跳過口令提示

你可能想要修改授權以讀寫模式訪問 socket 的組。例如,你想授權 mykvm 組,可創建下面的文件:

/etc/polkit-1/rules.d/50-libvirt.rules
/* Allow users in mykvm group to manage the libvirt
daemon without authentication */
polkit.addRule(function(action, subject) {
    if (action.id == "org.libvirt.unix.manage" &&
        subject.isInGroup("mykvm")) {
            return polkit.Result.YES;
    }
});

然後添加自己mykvm 組並重新登錄。可以將 mykvm 替換為你想要的任意組,只需確保該組存在,且用戶是該組的成員(詳情可參考用戶和用戶組)。

修改組之後不要忘記重新登錄才能生效。

基於文件的權限授權[編輯 | 編輯原始碼]

為了給 libvirt 組用戶定義基於文件的權限以管理虛擬機,取消下列行的注釋:

/etc/libvirt/libvirtd.conf
#unix_sock_group = "libvirt"
#unix_sock_ro_perms = "0777"  # set to 0770 to deny non-group libvirt users
#unix_sock_rw_perms = "0770"
#auth_unix_ro = "none"
#auth_unix_rw = "none"

有些資料提到可以通過改變某些特定 libvirt 目錄的權限以簡化管理。需要記住的是:包更新時,這些變更會丟失。如要修改這些系統目錄的權限,需要 root 用戶權限。

守護進程[編輯 | 編輯原始碼]

注意: Libvirt is moving from a single monolithic daemon to separate modular daemons, with the intention to remove the monolithic daemon in the future. See Libvirt daemons for more infomation.

libvirtd.servicevirtlogd.service這兩個服務單元都要啟動。可以把 libvirtd.service 設置為啟用,這時系統將同時啟用 virtlogd.servicevirtlockd.socket 兩個服務單元,因此後二者不必再設置為啟用

非加密的 TCP/IP sockets[編輯 | 編輯原始碼]

警告: 這種方法常用於在可信網絡中快速連接遠程域做協助。這是最不安全 的連接方式,應當僅僅用於測試或用於安全、私密和可信的網絡環境。這時 SASL 沒有啟用,所以所有的 TCP 通訊都是明文傳輸。在正式的應用場合應當始終 啟用 SASL。

編輯 /etc/libvirt/libvirtd.conf

/etc/libvirt/libvirtd.conf
listen_tls = 0
listen_tcp = 1
auth_tcp="none"

同時需要編輯 /etc/conf.d/libvirtd 以在監聽模式下啟動服務:

/etc/conf.d/libvirtd
LIBVIRTD_ARGS="--listen"

用主機名訪問虛擬機[編輯 | 編輯原始碼]

在非隔離的、橋接的網絡中從宿主機訪問客戶機,可以通過啟用 libvirt 提供的 libvirt 和/或 libvirt_guest NSS 模塊來實現。For the comparison of the two modules and technical details, see libvirt documentation.

nsswitch.conf(5) 中添加需要的模塊:

/etc/nsswitch.conf
hosts: files libvirt libvirt_guest dns myhostname
注意: pingssh 這類命令使用虛擬機主機名可以正常工作,但 hostnslookup 這類命令可能會失敗或產生非預期結果,因後者依賴 DNS 。應改用 getent hosts <vm-hostname> 命令。

測試[編輯 | 編輯原始碼]

測試 libvirt 在系統級工作是否正常:

$ virsh -c qemu:///system

測試 libvirt 在用戶會話級工作是否正常:

$ virsh -c qemu:///session

管理[編輯 | 編輯原始碼]

絕大部分的 libvirt 管理可以通過三個工具實現:virt-manager(圖形界面)、virshguestfish(它是 libguestfs 的一部分)。

virsh[編輯 | 編輯原始碼]

Visrsh 用於管理客戶(虛擬機),適用於腳本及虛擬環境管理工作。受限於與虛擬化環境通信的通道,絕大部分 virsh 命令需要管理員權限。儘管如此,一些典型的管理操作如域的創建、運行等也可以像 VirtualBox 那樣以普通用戶身份執行。

Virsh 允許帶命令行選項執行。如果不帶則進入其內置的交互式終端:virsh。交互式終端支持 tab 鍵命令補全。

從命令行執行:

$ virsh [可选项] <命令> [参数]...

在交互式終端裡運行:

virsh # <命令> [参数]...

幫助也是可用的:

$ virsh help [option*] or [group-keyword*]

存儲池[編輯 | 編輯原始碼]

存儲池是指保存的位置。Libvirt 中的定義相當於其他系統中虛擬磁盤虛擬機鏡像的概念。存儲池應該是一個目錄、一個網絡文件系統或一個分區(這也包括 LVM)。存儲池可以在活動與不活動之間切換,可以為其分配存儲空間。

系統級別,默認被激活的存儲池是 /var/lib/libvirt/images/;在用戶會話級別,virt-manager 將存儲池創建在 $XDG_DATA_HOME/images 目錄。

列出活動和不活動的存儲池的命令:

$ virsh pool-list --all

用 virsh 新建存儲池[編輯 | 編輯原始碼]

以下示例為添加存儲池、目錄和 LVM 卷的方法:

$ virsh pool-define-as name type [source-host] [source-path] [source-dev] [source-name] [<target>] [--source-format format]
$ virsh pool-define-as poolname dir - - - - /home/username/.local/libvirt/images
$ virsh pool-define-as poolname fs - -  /dev/vg0/images - mntpoint

上述示例僅僅定義了存儲池的信息,下面創建它:

$ virsh pool-build     poolname
$ virsh pool-start     poolname
$ virsh pool-autostart poolname

刪除它的命令:

$ virsh pool-undefine  poolname
提示:對於 LVM 存儲池而言:
  • 最佳實踐是僅把一個卷組分配給一個存儲池。
  • 請為存儲池選擇一個與 LVM 卷組不同的名字。否則當存儲池被刪除時,該卷組也將被刪除。

用 virt-manager 新建存儲池[編輯 | 編輯原始碼]

首先,連接到虛擬運行環境(例如 QEMU/KVM 的系統/用戶會話)。然後,右鍵點擊一個連接,選擇詳情;切換到存儲選項卡,點擊左下角的+,按照嚮導操作。

存儲卷[編輯 | 編輯原始碼]

存儲池被創建之後,就可以在存儲池中創建存儲卷。如果你想新建一個域(虛擬機),那麼這一步可以跳過,因為這一步可以在創建域的過程中完成。

用 virsh 新建卷[編輯 | 編輯原始碼]

新建卷,列出卷,變更卷大小,刪除卷:

$ virsh vol-create-as      poolname volumename 10GiB --format aw|bochs|raw|qcow|qcow2|vmdk
$ virsh vol-upload  --pool poolname volumename volumepath
$ virsh vol-list           poolname
$ virsh vol-resize  --pool poolname volumename 12GiB
$ virsh vol-delete  --pool poolname volumename
$ virsh vol-dumpxml --pool poolname volumename  # for details.

[編輯 | 編輯原始碼]

虛擬機被稱作「域」。如果你想在命令行下操作,使用 virsh 列出,創建,暫停,關閉……域。virt-viewer 可以用來查看使用 virsh 啟動的域。域的創建通常以圖形化的 virt-manager 或者命令行下的 virt-install(一個命令行工具,是 virt-install 包的一部分)完成。

創建新域通常需要安裝媒介,例如存儲池中的 .iso 文件或是直接從光驅安裝。

列出活動的和不活動的域:

# virsh list --all
注意: SELinux 有內置策略使在 /var/lib/libvirt/images/ 中的卷可以被訪問。如果你使用 SELinux 並且在卷方面有問題,確保卷位於該目錄,或是其它存儲池的標記正常。

用 virt-install 新建域[編輯 | 編輯原始碼]

本文或本章節的事實準確性存在爭議。

原因: /usr/share/libosinfo is not provided by any official packages, including libosinfo.(在 Talk:Libvirt#Where_is_'/usr/share/libosinfo/db/oses/os.xml'? 中討論)


對於很詳細的域(虛擬機)配置,可以#用 virt-manager 新建域更簡單地完成。但是,基礎配置同樣可以用 virt-install 完成並且同樣順利運行。最小配置包括 --name--memory,存儲(--disk--filesystem--nodisks)和安裝介質(通常來說是 .iso 文件或 CD)。查看 virt-install(1) 得到未列出的選項和更多的詳情。

安裝 Arch Linux(創建了 2 GiB qcow2 格式卷;用戶網絡):

$ virt-install  \
  --name arch-linux_testing \
  --memory 1024             \
  --vcpus=2,maxvcpus=4      \
  --cpu host                \
  --cdrom $HOME/Downloads/arch-linux_install.iso \
  --disk size=2,format=qcow2  \
  --network user            \
  --virt-type kvm

Fedora testing (Xen, 非默認池,無默認控制台):

$ virt-install  \
  --connect xen:///     \
  --name fedora-testing \
  --memory 2048         \
  --vcpus=2             \
  --cpu=host            \
  --cdrom /tmp/fedora20_x84-64.iso      \
  --os-type=linux --os-variant=fedora20 \
  --disk pool=testing,size=4            \
  --network bridge=br0                  \
  --graphics=vnc                        \
  --noautoconsole
$ virt-viewer --connect xen:/// fedora-testing

Windows:

$ virt-install \
  --name=windows7           \
  --memory 2048             \
  --cdrom /dev/sr0          \
  --os-variant=win7         \
  --disk /mnt/storage/domains/windows7.qcow2,size=20GiB \
  --network network=vm-net  \
  --graphics spice
提示:運行 osinfo-query --fields=name,short-id,version os 來獲得 --os-variant 的參數,這可以幫助定製域的一些規格。然而 --memory--disk 是必須被輸入的。如果需要查看這些規格,可以看看 /usr/share/libosinfo/db/oses/os.xml(譯註:此處可能已過時)。在安裝後,推薦安裝 Spice Guest Tools,其中包括 VirtIO 驅動。Windows 的 VirtIO 網絡驅動可通過 virtio-winAUR 獲得。要使用 VirtIO,需要在虛擬機 .xml 配置中使用 <model type='virtio' />。更多的信息可以參考 QEMU 頁面.

導入現有的卷:

$ virt-install  \
  --name demo  \
  --memory 512 \
  --disk /home/user/VMs/mydisk.img \
  --import

用 virt-manager 新建域[編輯 | 編輯原始碼]

首先,連接到虛擬運行環境(例如 QEMU/KVM system 或用戶 session,在連接上右擊並選擇 新建,然後跟隨嚮導完成。

  • 第四步中取消選中立即分配全部虛擬磁盤空間會加快創建過程並節省實際虛擬磁盤空間占用;然而,這將導致將來花費額外的磁盤整理時間。
  • 第五步中打開高級選項並確認虛擬化類型設為 kvm(這通常是首選模式)。如果要求附加的硬件配置,選中安裝前定製選項。

管理域[編輯 | 編輯原始碼]

啟動域:

$ virsh start domain
$ virt-viewer --connect qemu:///session domain

正常關閉域;強制關閉域:

$ virsh shutdown domain
$ virsh destroy  domain

在 libvirtd 啟動時自動啟動域:

$ virsh autostart domain
$ virsh autostart domain --disable

在宿主機關閉時自動關閉域:

通過使用 libvirt-guests.service Systemd 服務,運行中的域可以在宿主機關閉時自動掛起/關閉。同時這個服務還可以讓掛起/休眠的域在宿主機啟動的時候自動恢復。可查看 libvirt-guests(8) 了解相關選項。

編輯一個域的 XML 配置:

$ virsh edit domain

參考 libvirt 維基的 XML 格式一節了解關於 XML 配置文件的信息。

注意: 直接被 QEMU 啟動的虛擬機不被 libvirt 管理。

網絡[編輯 | 編輯原始碼]

這裡是有關 libvirt 網絡的的概述。

可將以下四種網絡連接到域:

  • bridge — 這是一個虛擬設備,它通過一個物理接口直接共享數據。使用場景為:宿主機有 靜態 網絡、不需與其它域連接、要占用全部進出流量,並且域運行於 系統 層級。網橋必須要在 libvirt 外配置,詳細操作可參考網橋。網橋創建後,需要將它指定到相應客戶機的 .xml 配置文件中。
  • network — 這是一個虛擬網絡,它可以與其它虛擬機共用。Libvirt 提供多種虛擬網絡模式,例如 NAT(Network address translation,網絡地址轉換)模式,路由模式和隔離模式。使用場景為:宿主機有 動態 網絡(例如:NetworkManager)或使用無線網絡。
  • macvtap — 直接連接到宿主機的一個物理網絡接口。相較橋接更加簡單,代價是宿主機無法通過該接口與域通信。Libvirt 可以很方便地配置該類網絡。
  • user — 本地網絡,僅用於用戶 會話

絕大多數用戶都可以通過 virsh 的各種可選項創建具有各種功能的網絡,一般來說通過 GUI 程序(像 virt-manager 之類)更方便,也可以按 #用 virt-install 新建域 所述實現。

注意:
  • libvirt 通過 dnsmasq 處理 DHCP 和 DNS 請求,為每個虛擬網絡創建一個實例。它也會為特定的路由添加 iptables 規則並啟用 ip_forward 內核參數。這也意味着宿主機上無需預先運行 dnsmasq(並可能干擾到 libvirt 的 dnsmasq 實例)。
  • 如果無法啟動默認網絡,請確保已安裝 iptables-nftdnsmasq

通過以下命令獲取虛擬機的 IP(假設它連接到 default 網絡並通過 DHCP 獲取 IP):

$ virsh net-dhcp-leases default

如果 VM 上運行有 qemu-guest-agent

$ virsh domifaddr --source agent $vm

$vm 替換為實際的虛擬機名稱(或域 ID)。

管理並修改網絡[編輯 | 編輯原始碼]

修改網絡前建議先閱讀 libvirt 維基的用於虛擬網絡的基本命令行用法一節。另外也建議通過 libvirt 網絡維基了解用法。

IPv6[編輯 | 編輯原始碼]

當通過任何配置工具試圖添加 IPv6 地址時,你可能會遇到這樣的錯誤:

Check the host setup: enabling IPv6 forwarding with RA routes without accept_ra set to 2 is likely to cause routes loss. Interfaces to look at: eth0

要修復這個問題,運行如下命令(將 eth0 改為你的物理接口的名稱),並重新啟動系統。

# sysctl net.ipv6.conf.eth0.accept_ra=2

Macvtap[編輯 | 編輯原始碼]

要創建 macvtap 網絡,先創建該文件:

macvtap.xml
<network>
  <name>macvtap-net</name>
  <forward mode='bridge'>
    <interface dev='eth0'/>
  </forward>
</network>

然後定義並啟用網絡:

$ virsh net-define macvtap.xml
$ virsh net-autostart macvtap-net
$ virsh net-start macvtap-net

現在已創建好 macvtap-net 網絡並已持久化,它通過 eth0 橋接到外部網絡。

警告: 宿主機無法通過該網絡與域通信。宿主機的網絡不受影響,域也可以與該網絡的其它機子通信,但不能與宿主機本身通信。可參考 libvirt 維基繞過該限制。

快照[編輯 | 編輯原始碼]

快照保存某一時刻域的磁盤、內存和設備狀態以供將來使用。快照有很多用處,例如在進行可能的破壞性操作時保存一份乾淨的域狀態。快照使用唯一名稱進行標識。

快照保存在卷之中,卷必須為 qcow2 或 raw 格式。快照使用增量存儲,所以並不會占用很多空間。

創建快照[編輯 | 編輯原始碼]

本文內容或本節內容已經過期。

原因: Some of this data appears to be dated. (在Talk:Libvirt討論)

Once a snapshot is taken it is saved as a new block device and the original snapshot is taken offline. Snapshots can be chosen from and also merged into another (even without shutting down the domain).

Print a running domain's volumes (running domains can be printed with virsh list):

# virsh domblklist domain
 Target     Source
 ------------------------------------------------
 vda        /vms/domain.img

To see a volume's physical properties:

# qemu-img info /vms/domain.img
 image: /vms/domain.img
 file format: qcow2
 virtual size: 50G (53687091200 bytes)
 disk size: 2.1G
 cluster_size: 65536

Create a disk-only snapshot (the option --atomic will prevent the volume from being modified if snapshot creation fails):

# virsh snapshot-create-as domain snapshot1 --disk-only --atomic

List snapshots:

# virsh snapshot-list domain
 Name                 Creation Time             State
 ------------------------------------------------------------
 snapshot1           2012-10-21 17:12:57 -0700 disk-snapshot

One can then copy the original image with cp --sparse=true or rsync -S and then merge the original back into snapshot:

# virsh blockpull --domain domain --path /vms/domain.snapshot1

domain.snapshot1 becomes a new volume. After this is done the original volume (domain.img and snapshot metadata can be deleted. The virsh blockcommit would work opposite to blockpull but it seems to be currently under development (including snapshot-revert feature, scheduled to be released sometime next year.

其它管理操作[編輯 | 編輯原始碼]

連接到非默認的虛擬運行環境:

$ virsh --connect xen:///
virsh # uri
xen:///

通過 SSH 連接到 QEMU 虛擬運行環境,並且以相同方式登錄:

$ virsh --connect qemu+ssh://username@host/system
$ LIBVIRT_DEBUG=1 virsh --connect qemu+ssh://username@host/system

通過 SSH 連接到一個圖形控制台:

$ virt-viewer  --connect qemu+ssh://username@host/system domain
$ virt-manager --connect qemu+ssh://username@host/system domain
注意: 如果你在連接 RHEL 服務器(或其他不是 Arch 的服務器)時出現問題,可嘗試這裡提到的兩個方案:FS#30748FS#22068

連接到 VirtualBox(libvirt 對 VirtualBox 的支持尚不穩定,可能會導致 libvirtd 崩潰):

$ virsh --connect vbox:///system

網絡配置:

$ virsh -c qemu:///system net-list --all
$ virsh -c qemu:///system net-dumpxml default

Hooks[編輯 | 編輯原始碼]

Hooks are scripts that are triggered by different events happening while starting and running the libvirt daemon. They can be used to execute commands needed in preparation to launch a guest like setup networks or reserve memory.

The following hooks exists:

  • daemon - occasions to trigger: start, shutdown, reload
  • qemu - occasions to trigger: prepare, prepare, start, started, stopped, release, migrate, restore, reconnect, attach
  • lxc - occasions to trigger: prepare, start, started, stopped, release, reconnect
  • libxl - occasions to trigger: prepare, start, started, stopped, release migrate, reconnect
  • network - occasions to trigger: start, started, stopped, port-created, updated, port-deleted

See the libvirt Documentation for details about each hook and trigger.

Create a hook[編輯 | 編輯原始碼]

Hooks are represented by scripts located at /etc/libvirt/hooks. If the folder does not exist, you have to create it. Each hook is represented by a script in this folder with the same name (e.g. /etc/libvirt/hooks/qemu) or a subfolder (e.g. /etc/libvirt/hooks/qemu.d/). The later can contain different scripts, which are all run at the trigger points. The scripts are run like any other scripts, so they need to start whith the declaration of the command interpreter to use (e.g. #!/bin/bash). The script have to be executable by the libvirt user (chown +x /etc/libvirt/hooks/qemu).

Everytime a trigger point is met, the script is run. For example, the daemon script would run at least two times in a start/stop cycle of the system, at start and at shutdown. To run an command only at a given point, you have to implement conditions in the script. To do this, libvirt passes parameters which can be used to identify the current trigger condition.

According to the libvirt documentation these parameters are defined as follows:

  • Parameter 1: The name of the object involved in the operation
  • Parameter 2: The name of the operation being performed
  • Parameter 3: Used if a sub-operation is to be named
  • Parameter 4: An extra argument if needed

If one of the arguments is not applicable, a dash is passed.

注意: If the hooks are not working after creating your script, try restarting the libvirt daemon.

示例[編輯 | 編輯原始碼]

To run an command everytime you start an qemu guest, before any ressources are allocated, you can use the qemu hook. At this point, libvirt runs the hooks like this: /etc/libvirt/hooks/qemu <guest_name> prepare begin - The script for this could like this:

/etc/libvirt/hooks/qemu
#!/bin/bash
guest_name="$1"
libvirt_task="$2"
if [ "$libvirt_task" = "prepare" ]; then
	<run some important code here>
fi

If the guest is stopped, the same script would be run, but this time the daemon would start the command like this: /etc/libvirt/hooks/qemu <guest_name> stopped end -

宿主機與虛擬機間共享數據[編輯 | 編輯原始碼]

Virtio-FS[編輯 | 編輯原始碼]

注意: Virtio-FS is not supported in QEMU/KVM user sessions.

The description here will use hugepages to enable the usage of shared folders. Sharing files with Virtio-FS lists an overview of the supported options to enable filesharing with the guest.

First you need to enable hugepages which are used by the virtual machine:

/etc/sysctl.d/40-hugepage.conf
vm.nr_hugepages = nr_hugepages

To determine the number of hugepages needed check the size of the hugepages:

$ grep Hugepagesize /proc/meminfo

The number of hugepages is memory size of virtual machine / Hugepagesize. Add to this value some additional pages. You have to reboot after this step, so that the hugepages are allocated.

Now you have to prepare the configuration of the virtual machine:

# virsh edit name_of_virtual_machine
<domain>
...
  <memoryBacking>
    <hugepages/>
  </memoryBacking>
...
  <cpu ...>
    <numa>
      <cell memory='memory size of virtual machine' unit='KiB' memAccess='shared'/>
    </numa>
  </cpu>
...
  <devices>
    ...
    <filesystem type='mount' accessmode='passthrough'>
      <driver type='virtiofs'/>
      <source dir='path to source folder on host'/>
      <target dir='mount_tag'/>
    </filesystem>
    ...
  </devices>
</domain>

It is necessary to add the NUMA definition so that the memory access can be declared as shared. id and cpus values for NUMA will be inserted by virsh.

It should now be possible to mount the folder in the shared machine:

# mount -t virtiofs mount_tag /mnt/mount/path

Add the following fstab entry to mount the folder automatically at boot:

/etc/fstab
...
mount_tag /mnt/mount/path virtiofs rw,noatime,_netdev 0 0

9p[編輯 | 編輯原始碼]

File system directories can be shared using the 9P protocol. Details are available in QEMU's documentation of 9psetup.

Configure the virtual machine as follows:

<domain>
...
  <devices>
    ...
    <filesystem type="mount" accessmode="mapped">
      
<target dir="mount_tag"/> </filesystem> </devices> </domain>

Boot the guest and mount the shared directory from it using:

# mount -t 9p -o trans=virtio,version=9p2000.L mount_tag /path/to/mount_point/on/guest

See https://docs.kernel.org/filesystems/9p.html for more mount options.

To mount it at boot, add it to the guest's fstab:

/etc/fstab
...
mount_tag	/path/to/mount_point/on/guest	9p	trans=virtio,version=9p2000.L	0 0

The module for the 9p transport (i.e. 9pnet_virtio for trans=virtio) will not be automatically loaded, so mounting the file system from /etc/fstab will fail and you will encounter an error like 9pnet: Could not find request transport: virtio. The solution is to preload the module during boot:

/etc/modules-load.d/9pnet_virtio.conf
9pnet_virtio

Samba / SMB[編輯 | 編輯原始碼]

An other easy way to share data between guest and host is to use the smb protocol. While performance and latency may not be as good as in the other described ways, its sufficient for simple tasks like transfering simple files like images or documents from and to the guest.

The smb server can be set up directly on either the host, or the guest, for example using Samba, eliminating the need for a dedicated file server. Windows guests have the ability to create smb shares included right after installation (Microsoft Supportpage).

One possible way to access the share under linux (either from the host, or from the guest, depending, where you have installed your server) is to create an entry in your fstab. The samba package is required.

/etc/fstab
#Accessing a samba share on my vm from the host
//my_vm/my_share /home/archuser/my_vm cifs _netdev,noauto,nofail,user,credentials=/home/archuser/.config/my_vm.key,gid=1000,uid=984 0 0

_netdev,noauto,nofail ensures that the share is only mounted when needed without causing issues if the vm is not booted. user,credentials=/home/user/.config/my_vm.key,gid=1000,uid=984 gives you the ability to mount the share on the fly while first accessing it, without needing a password.

UEFI 支持[編輯 | 編輯原始碼]

Libvirt 可以通過 QEMU 和 OVMF 來支持 UEFI 虛擬機。

安裝 edk2-ovmf

重啟 libvirtd

你現在就可以創建 UEFI 虛擬機了。通過 virt-manager 創建一台虛擬機,在到達新建虛擬機嚮導的最後一頁時,進行如下操作:

  • 勾選在安裝前自定義配置,之後點擊完成
  • 概況屏幕, 將固件改為:
    • UEFI x86_64: /usr/share/edk2/x64/OVMF_CODE.4m.fd:無安全啟動支持的 x64 UEFI,
    • UEFI x86_64: /usr/share/edk2/x64/OVMF_CODE.secboot.4m.fd:帶安全啟動支持的 x64 UEFI(無預置證書)。
  1. 點擊應用
  • 點擊開始安裝

參考 Fedora:Using UEFI with QEMU 獲得更多信息。

小技巧[編輯 | 編輯原始碼]

Python 連接代碼[編輯 | 編輯原始碼]

libvirt-python/usr/lib/python3.x/site-packages/libvirt.py 提供了一個 Python API。

常用例子在 /usr/share/doc/libvirt-python-your_libvirt_version/examples/ 給出。

一個使用 qemu-desktopopenssh 的例子(非官方):

#! /usr/bin/env python3
import socket
import sys
import libvirt

conn = libvirt.open("qemu+ssh://xxx/system")
print("Trying to find node on xxx")
domains = conn.listDomainsID()
for domainID in domains:
    domConnect = conn.lookupByID(domainID)
    if domConnect.name() == 'xxx-node':
        print("Found shared node on xxx with ID {}".format(domainID))
        domServ = domConnect
        break

先進格式化 4K 原生硬盤[編輯 | 編輯原始碼]

To turn a disk into an Advanced Format 4Kn disk, both its physical and logical sector size needs to be set to 4 KiB. For virtio-blk and virtio-scsi this can be done by setting the logical_block_size and physical_block_size options with the <blockio> element. For example:

# virsh edit name_of_virtual_machine
<domain>
  ...
  <devices>
    ...
    <disk type='file' device='disk'>
      ..
      <blockio logical_block_size='4096' physical_block_size='4096'/>
    </disk>
    ...
  </devices>
</domain>

控制 QEMU[編輯 | 編輯原始碼]

Libvirt is capable of passing on QEMU command line arguments to the underlying QEMU instance running the VM. This functionality is highly useful when libvirt does not provide QEMU features (yet). For examples, see the entire Intel GVT-g article.

modify VM XML schema for QEMU[編輯 | 編輯原始碼]

This serves to enable QEMU-specific elements. Change

$ virsh edit vmname
<domain type='kvm'>

to

$ virsh edit vmname
<domain xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0' type='kvm'>

QEMU 命令行參數[編輯 | 編輯原始碼]

In libvirt, QEMU command line arguments separated by whitespaces need to be provided separately.

The correct location to insert them is at the end of the <domain> element, i. e. right above the closing </domain> tag.

-display gtk,gl=es,zoom-to-fit=off

Becomes

$ virsh edit vmname
...
  </devices>
  <qemu:commandline>
    <qemu:arg value="-display"/>
    <qemu:arg value="gtk,gl=es,zoom-to-fit=off"/>
  </qemu:commandline>
</domain>

排障[編輯 | 編輯原始碼]

系統實例下的 PulseAudio[編輯 | 編輯原始碼]

PulseAudio 守護進程通常在你的普通用戶下運行,並且只接受來自相同用戶的連接。然而 libvirt 默認使用 root 運行 QEMU。為了讓 QEMU 在普通用戶下運行,編輯 /etc/libvirt/qemu.conf 並將 user 設置為你的用戶名。

user = "dave"

你同樣需要告訴 QEMU 使用 PulseAudio 後端並識別要連接的服務器。使用 virsh edit 將如下內容添加到你的域配置中:

  <audio id="1" type="pulseaudio" serverName="/run/user/1000/pulse/native">
    <input latency="20000"/>
    <output latency="20000"/>
  </audio>

1000 是你的用戶 ID,如有必要可修改。

You can omit the latency settings (in microseconds) but using the defaults might result in crackling.

Hypervisor CPU use[編輯 | 編輯原始碼]

Default VM configuration generated by virt-manager may cause rather high (10-20%) CPU use caused by the QEMU process. If you plan to run the VM in headless mode, consider removing some of the unnecessary devices.

Virtual machine cannot be un-paused on virt-manager[編輯 | 編輯原始碼]

If you are using a disk image format such as qcow2 which has a specified virtual capacity, but only stores what is needed, then you need to have space on the host partition for the image to grow. If you see I/O related errors when attempting to start the VM, it's possible that the host partition holding the virtual disk image is full. You can run df -h on the host to verify how much free space is available.

If this is the case, see System maintenance#Clean the filesystem for ways to free up space.

Redirect USB Device is greyed out in virt-manager[編輯 | 編輯原始碼]

If the Redirect USB Device menu item is greyed out, check that the following hardware is configured for the VM:

  • A USB Controller.
  • One or more USB Redirectors.

Error starting domain: Requested operation is not valid[編輯 | 編輯原始碼]

When you try to open a virtual machine this error may pop up. This is because when you try to open a existing virtual machine libvirt tries to search for the default network which is not available. To make it available you have to autostart your network interface so that whenever your restart your computer your network interface is always active. See libvirt networking page.

Look at the name of your network interface with the following command:

# virsh net-list --all

To autostart your network interface:

# virsh net-autostart name_of_the_network

To start your network interface:

# virsh net-start name_of_the_network

Virt Manager Error 'Virt Manager doesn't have search permissions'[編輯 | 編輯原始碼]

Ensure the folder containing your virtual machine files and installation ISO are owned by the libvirt-qemu group

$ sudo chown -R $USER:libvirt-qemu /path/to/virtual/machine

參閱[編輯 | 編輯原始碼]