【qemu+libvirt+virt-manager源码安装】

0. 前言

编译需要用到高版本python(>=3.8),参考附录查看教程,我使用的python3.11,所有后文的python3都是它的链接。

1. 源码安装qemu

1.1 源码安装

apt install gtk+-3.0	# 后面qemu编译依赖用的到
wget https://download.qemu.org/qemu-9.1.0-rc2.tar.xz
tar xvJf qemu-9.1.0-rc2.tar.xz
cd qemu-9.1.0-rc2
mkdir -p build
cd build
# if you want the x86 target too you can add "x86-softmmu" in the target list
../configure --target-list=aarch64-linux-user,loongarch64-linux-user,mips64-linux-user,x86_64-linux-user,aarch64-softmmu,loongarch64-softmmu,mips64-softmmu,x86_64-softmmu --enable-debug --enable-gtk --enable-gtk-clipboard -Dbuildtype=release -Doptimization=s --disable-debug-info
make -j16
make install
  • --enable-debug:使能qemu的debug功能
  • --enable-gtk:如果不指定,当系统没有相应gtk包时,编译过程不会提示,安装使用后,启动虚拟机将看不到图像,所以请务必显式指定。
  • --enable-gtk-clipboard:可以直接将复制的内容粘贴到虚拟机。
  • -Dmesonoptname=val:传递给meson的选项,qemu实际上是使用meson构建的,configure只是个套壳,meson configure可以查看当前构建选项和说明,例如,-Doptimization=s:开启速度优先优化。
  • --disable-debug-info:关闭qemu的调试信息
  • --target-list如果不指定,会编译所有架构虚拟机,很慢。
    • xxx-softmmu 表示的是模拟整个物理机,使用 qemu-system-xxx 命令。
    • xxx-linux-user 仅模拟用户应用程序,使用 qemu-xxx 命令。

1.2 命令行启动测试

安装镜像

qemu-img create -f qcow2 /tmp/vm-disk.qcow2 40G
qemu-system-x86_64 -cpu host -enable-kvm -hda /tmp/vm-disk.qcow2 -cdrom /path/to/centos.iso

注意:-enable-kvmaccel=kvm 一定要加上,利用kvm实现硬件加速,速率块很多,OS的CPU指令不用再经过Qemu转译,直接运行。

1.3 测试qemu监控器控制台

可以在qemu的UI界面,通过view->compatmonitor打开控制态。注意只有通过命令行(qemu-system-ARCH)启动虚拟机时才会有该选项。

qemu-system-x86_64 -m 4096 -smp 4 -hda /var/lib/libvirt/images/generic -cpu host -enable-kvm

如果是通过libvird启动的虚拟机(例如virt-manager工具),它是通过vnc或spice会话,和虚拟机的输出连接的,这样是不能直接访问qemu的监控器的,但是可以通过virsh这个工具,向qemu发送命令来进入。

1.4 可能遇到的问题

  • 问题:gtk initialization failed
  • 原因:大概率是因为你用root身份(和环境)运行qemu,qemu-system-xxx会调用gtk的sdk,其中一个接口是gtk_init_check,它会检测当前环境变量是否有DISPLAY,而root的环境默认是没有这个环境变量的。
  • 解决:使用图形用户(即你桌面用户)来运行qemu-system-xxx,或者将桌面用户的DISPLAY变量拷贝给root。
virsh qemu-monitor-command COMMAND

2. 源码安装libvirt

2.1 编译安装

meson setup build -Dsystem=true -Ddriver_libvirtd=enabled -Ddriver_remote=enabled -Dsystem=true -Ddriver_qemu=enabled -Ddocs=disabled
ninja -C build
ninja -C build test
ninja -C build install

2.2 启动服务

上安装完成后,相应服务文件会安装到指定目录,需要手动开启服务

systemctl enable libvirtd virtlogd	# 设定开机启动该服务
systemctl start libvirtd virtlogd	# 立即启动该服务
systemctl status libvirtd virtlogd	# 查看启动状态

2.3 可能遇到的问题

  • 问题:systemctl status libvirtd报错
apabilities for /usr/local/bin/qemu-system-x86_64: internal error: Failed to start QEMU binary /usr/local/bin/qemu-system-x86_64 for probing: libvirt:  error : 权限不够
  • 原因:/usr/local/bin/qemu-system-x86_64是源码安装qemu时的默认安装路径,如果历史上,通过apt安装过libvirtd包,安装包时,会对libvirtd生成apparmor的策略文件(不同打包应用不同,有可能也没有该逻辑),限制其访问范围,其中可访问的范围包括/usr/bin /usr/sbin,但是不包括/usr/local,因此如果你的环境开启了apparmor,且之前通过源安装过libvirtd,则大概率会报该错。

  • 解决:很简单,取消apparmor对libvirtd的限制即可,aa-disable /usr/sbin/libvirtd

  • 问题:'Failed to connect socket to '/var/run/libvirt/virtlogd-sock': 没有那个文件或目录',查看systemctl status libvirtd日志Failed to connect socket to '/var/run/libvirt/virtlogd-sock': 拒绝连接,尝试手动启动virtlogdsystemclt start virtlogd报错:Reason: Unit virtlogd.service is masked.,查看/etc/systemd/system/virtlogd.service,被链接到了/dev/null。同样的还有目录/var/lib/systemd/deb-systemd-helper-masked/virt相关的sock文件

  • 原因:猜测是因为我之前使用apt安装过libvirtd,之后把它卸载,导致它被链接到空。

  • 解决:删除它重新使能、启动服务即可。

3. 源码安装virt-manager

3.1 源码安装

tar xf virt-manager-4.1.0.tar.gz
cd virt-manager-4.1.0
python3 setup.py build
python3 setup.py install

3.2 可能遇到的问题

  • 问题:编译报错
subprocess.CalledProcessError: Command '['/usr/bin/rst2man', '--strict', 'man/virt-manager.rst']' returned non-zero exit status 1.
  • 解决:
pip3 install docutils
  • 问题:运行 virt-manager 报错
pygobject3 3.31.3 or later is required.
# or
ModuleNotFoundError: No module named 'gi'
  • 解决:
pip3 install PyGObject
  • 问题:ERROR: Failed building wheel for pycairo

  • 解决:apt install libcairo-dev

  • 问题:../meson.build:29:9: ERROR: Dependency 'gobject-introspection-1.0' is required but not found.

  • 解决:apt install libgirepository1.0-dev

  • 问题:Dependency gobject-introspection-1.0 found: NO. Found 1.58.3 but need: '>= 1.64.0'

  • 解决:更新gobject-introspection-1.0,README没有写编译方法,参考官网

meson setup _build
cd _build
# To see the build options run "meson configure"
meson compile
  • 问题:meson.build:1:0: ERROR: Meson version is 0.61.2 but project requires >= 1.2.0

  • 解决:python3 -m pip install meson

  • 问题:meson.build:25:2: ERROR: Problem encountered: Requires Python >=3.8, 3.7 found.

  • 解决:源码安装python3.11

  • 问题:meson.build:29:8: ERROR: python3 is missing modules: setuptools

  • 解决:python3 -m pip install setuptools

  • 问题:Run-time dependency glib-2.0 found: NO (tried pkgconfig and cmake)

  • 解决:apt install gir1.2-glib-2.0

  • 问题:Run-time dependency libpcre2-8 found: NO (tried pkgconfig and cmake)git

  • 解决:apt install libpcre2-dev

  • 问题:fatal: unable to access 'https://gitlab.gnome.org/GNOME/gvdb.git/'

  • 解决:

vim ./subprojects/gvdb.wrap # 编辑url如下
url=https://github.com/GNOME/gvdb.git
  • 问题:ValueError: Namespace Gdk not available
  • 解决:
$ python3 -m pip install Gdk
$ apt-get install libgtk-3-dev
$ export GI_TYPELIB_PATH=/usr/lib/x86_64-linux-gnu/girepository-1.0
$ echo 'export GI_TYPELIB_PATH=/usr/lib/x86_64-linux-gnu/girepository-1.0' >> ~/.bashrc
  • 问题:ModuleNotFoundError: No module named 'libvirt'
  • 解决:
pip3 install libvirt-python

如果安装失败,则只能手动源码安装了

tar xf libvirt-python-10.6.0.tar.gz
cd libvirt-python-10.6.0
pip3 install build # 也可手动装
export PKG_CONFIG_PATH=/usr/lib64/pkgconfig/
python3 -m build
python3 -m pip install .
  • 问题:ModuleNotFoundError: No module named 'libxml2'
  • 解决:pip3 install libxml2,大概率找不到包,手动去官网下源码安装。
tar xf libxml2-python3-2.9.5.tar.gz
cd libxml2-python3-2.9.5
python3 setup.py build # 大概率会报错,参考后文修改
python3 setup.py install
python3 setup

截止2024/4/19,libxml2-python3的源码直接使用python3.12编译会报错

/usr/include/python3.12/object.h:971:41: error: expected ‘(’ before ‘PyType_HasFeature’
 #define PyType_FastSubclass(type, flag) PyType_HasFeature((type), (flag))
                                         ^~~~~~~~~~~~~~~~~
/usr/include/python3.12/unicodeobject.h:115:5: note: in expansion of macro ‘PyType_FastSubclass’
     PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_UNICODE_SUBCLASS)
     ^~~~~~~~~~~~~~~~~~~
libxml.c:297:15: note: in expansion of macro ‘PyUnicode_Check’
     } else if PyUnicode_Check (ret) {
               ^~~~~~~~~~~~~~~
libxml.c:297:37: error: expected ‘;’ before ‘{’ token
     } else if PyUnicode_Check (ret) {

源码有些地方需要修改(很少),修改内容如下(格式为git补丁,直接补丁应用,参考后文,也可手动修改)

From: leifeng <leifeng@leifeng.com>
Date: Mon, 19 Aug 2024 17:20:23 +0800
Subject: [PATCH] fix python3.12 compiling err

---
 libxml.c |  4 ++--
 types.c  | 12 ++++++------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/libxml.c b/libxml.c
index 5b1ff6e..c18a9d1 100644
--- a/libxml.c
+++ b/libxml.c
@@ -294,7 +294,7 @@ xmlPythonFileReadRaw (void * context, char * buffer, int len) {
        lenread = PyBytes_Size(ret);
        data = PyBytes_AsString(ret);
 #ifdef PyUnicode_Check
-    } else if PyUnicode_Check (ret) {
+    } else if (PyUnicode_Check(ret)){
 #if PY_VERSION_HEX >= 0x03030000
         Py_ssize_t size;
        const char *tmp;
@@ -359,7 +359,7 @@ xmlPythonFileRead (void * context, char * buffer, int len) {
        lenread = PyBytes_Size(ret);
        data = PyBytes_AsString(ret);
 #ifdef PyUnicode_Check
-    } else if PyUnicode_Check (ret) {
+    } else if (PyUnicode_Check(ret)) {
 #if PY_VERSION_HEX >= 0x03030000
         Py_ssize_t size;
        const char *tmp;
diff --git a/types.c b/types.c
index 124af56..f5c99ad 100644
--- a/types.c
+++ b/types.c
@@ -602,16 +602,16 @@ libxml_xmlXPathObjectPtrConvert(PyObject *obj)
     if (obj == NULL) {
         return (NULL);
     }
-    if PyFloat_Check (obj) {
+    if (PyFloat_Check(obj)) {
         ret = xmlXPathNewFloat((double) PyFloat_AS_DOUBLE(obj));
-    } else if PyLong_Check(obj) {
+    } else if (PyLong_Check(obj)) {
 #ifdef PyLong_AS_LONG
         ret = xmlXPathNewFloat((double) PyLong_AS_LONG(obj));
 #else
         ret = xmlXPathNewFloat((double) PyInt_AS_LONG(obj));
 #endif
 #ifdef PyBool_Check
-    } else if PyBool_Check (obj) {
+    } else if (PyBool_Check(obj)) {
 
         if (obj == Py_True) {
           ret = xmlXPathNewBoolean(1);
@@ -620,14 +620,14 @@ libxml_xmlXPathObjectPtrConvert(PyObject *obj)
           ret = xmlXPathNewBoolean(0);
         }
 #endif
-    } else if PyBytes_Check (obj) {
+    } else if (PyBytes_Check(obj)) {
         xmlChar *str;
 
         str = xmlStrndup((const xmlChar *) PyBytes_AS_STRING(obj),
                          PyBytes_GET_SIZE(obj));
         ret = xmlXPathWrapString(str);
 #ifdef PyUnicode_Check
-    } else if PyUnicode_Check (obj) {
+    } else if (PyUnicode_Check(obj)) {
 #if PY_VERSION_HEX >= 0x03030000
         xmlChar *str;
        const char *tmp;
@@ -650,7 +650,7 @@ libxml_xmlXPathObjectPtrConvert(PyObject *obj)
        ret = xmlXPathWrapString(str);
 #endif
 #endif
-    } else if PyList_Check (obj) {
+    } else if (PyList_Check(obj)) {
         int i;
         PyObject *node;
         xmlNodePtr cur;
-- 
2.20.1

将上面内容拷贝到本地xxx.patch

tar xf libvirt-python-10.6.0.tar.gz
cd libvirt-python-10.6.0
git init
git add .
git commit -m 'init'
git am ../xxx.patch
  • 问题:ModuleNotFoundError: No module named 'requests'
  • 解决:python3 -m pip install requests,阿里源有这个包

3.3 到这virt-manager可以运行

但是点击创建虚拟机图标,没有弹窗,无反应,尝试以调试模式启动virt-manager查看报错

virt-manager --debug

可能依次看到如下报错:

  • 问题:ValueError: Namespace GtkSource not available

  • 解决:apt install gir1.2-gtksource-3.0

  • 问题:ValueError: Namespace Vte not available

  • 解决:apt install vte-2.91

  • 问题:ValueError: Namespace GtkVnc not available

  • 解决:apt install gir1.2-gtk-vnc-2.0

  • 问题:cannot open display

  • 解决:同前文gtk initialization failed的解决办法

  • 问题:TypeError: iter() returned non-iterator of type 'xmlCoreDepthFirstItertor'

  • 原因:libxml2-python3-3.9.5的bug,参考这里修改

  • 解决:回到前面libxml2-python3编译环节,参考其中一个问题修复方式,打完如下补丁(可手动修改),重新编译安装即可。

From eddab8afdcd6d2e10cc2b7a0ad843881b5ba1a2a Mon Sep 17 00:00:00 2001
From: leifeng <leifeng@leifeng.com>
Date: Tue, 20 Aug 2024 16:31:48 +0800
Subject: [PATCH] fix: python3.12 TypeError: iter() returned non-iterator of
 type 'xmlCoreDepthFirstItertor'

---
 libxml2.py | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libxml2.py b/libxml2.py
index 9712d16..f359360 100644
--- a/libxml2.py
+++ b/libxml2.py
@@ -530,7 +530,7 @@ class xmlCoreDepthFirstItertor:
         self.parents = []
     def __iter__(self):
         return self
-    def next(self):
+    def __next__(self):
         while 1:
             if self.node:
                 ret = self.node
@@ -542,6 +542,7 @@ class xmlCoreDepthFirstItertor:
             except IndexError:
                 raise StopIteration
             self.node = parent.next
+    next = __next__
 
 #
 # implements the breadth-first iterator for libxml2 DOM tree
@@ -552,7 +553,7 @@ class xmlCoreBreadthFirstItertor:
         self.parents = []
     def __iter__(self):
         return self
-    def next(self):
+    def __next__(self):
         while 1:
             if self.node:
                 ret = self.node
@@ -564,6 +565,7 @@ class xmlCoreBreadthFirstItertor:
             except IndexError:
                 raise StopIteration
             self.node = parent.children
+    next = __next__
 
 #
 # converters to present a nicer view of the XPath returns
-- 
2.20.1


4. 附录

4.1 源码安装python3.11

qemu-9.x,virt-manager-4.1需要用到3.8以上的python,这里我安装的python3.11
后续编译请注意python版本,不要混用。通过修改软链接可手动切换python3版本

ln -sf python3.7 /bin/python3
ln -sf python3.11 /bin/python3

4.2 配置python国内代理镜像站

下面选择一个执行就可以了

# 清华源
pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
# 阿里源
pip3 config set global.index-url https://mirrors.aliyun.com/pypi/simple/
# 腾讯源
pip3 config set global.index-url https://mirrors.cloud.tencent.com/pypi/simple
# 豆瓣源
pip3 config set global.index-url https://pypi.douban.com/simple/

4.3 配置pip代理

root@PC:~# cat /root/.config/pip/pip.conf
[global]
proxy=http://127.0.0.1:8000 # 你自己的代理
  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值