正如本系列第一篇文章架构图所示Ubuntu12.10 下搭建基于KVM-QEMU的虚拟机环境(一),除了在内核空间的KVM模块之外,在用户空间需要QEMU来模拟所需要CPU和设备模型以及用于启动客户机进程,这样才有了一个完整的KVM运行环境。而qemu-kvm是为了针对KVM专门做了修改和优化的QEMU分支,具体关于KVM,QEMU-KVM的介绍还是请参阅相关的官方网站:和。
KVM内核模块我们打算就用系统自带的kvm.ko,我们主要编译可能需要维护的用户空间部分——启用kvm的qemu。同样,我们首先从https://launchpad.net/ubuntu/+source/qemu/1.4.0+dfsg-1expubuntu4 获得源码包:qemu_1.4.0+dfsg.orig.tar.xz,qemu_1.4.0+dfsg-1expubuntu4.debian.tar.gz,qemu_1.4.0+dfsg-1expubuntu4.dsc
下载以后将上述三个文件上传至编译目录: ~/workroom/qemu-kvm/。
解开源码
dev@xxx:~/workroom/ qemu-kvm $ sudo dpkg-source –xqemu_1.4.0+dfsg-1expubuntu4.dsc
Qemu的编译我们需要修改一下缺省的配置参数,打开下面目录下的rules文件,修改部分用红色表示出来,主要目的是加上支持spice,usbredir等功能以及去掉对其他平台的编译(只保留X86_64):
dev@xxx:~/workroom/ qemu-kvm/qemu-1.4.0+dfsg/debian $ sudo vi rules
#!/usr/bin/make -f
#
# $Id: rules 391 2009-03-07 05:21:19Z aurel32 $
#
# support parallel build using DEB_BUILD_OPTIONS=parallel=N
ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
MAKEFLAGS += -j$(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
endif
# Packaging version
DEB_VERSION := $(shell dpkg-parsechangelog | egrep '^Version:' | cut -f 2 -d ' ')
# Compiler flags
CFLAGS = $(shell dpkg-buildflags --get CFLAGS) $(shell dpkg-buildflags --get CPPFLAGS)
LDFLAGS = $(shell dpkg-buildflags --get LDFLAGS) -Wl,--as-needed
# Architecture/system specific configuration
DEB_HOST_ARCH = $(shell dpkg-architecture -qDEB_HOST_ARCH)
DEB_HOST_ARCH_OS = $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)
# we add another set of configure options from debian/control
common_configure_opts = \
--with-pkgversion="Debian $(DEB_VERSION)" \
--extra-cflags="$(CFLAGS)" \
--extra-ldflags="$(LDFLAGS)" \
--prefix=/usr \
--sysconfdir=/etc \
--libexecdir=/usr/lib \
--disable-blobs \
--disable-strip \
--with-system-pixman \
--enable-linux-aio \
--enable-kvm \
--enable-spice \
--enable-uuid \
--enable-usb-redir \
--enable-vhost-net \
--disable-guest-agent \
--target-list=x86_64-softmmu \
--interp-prefix=/etc/qemu-binfmt/%M \
--localstatedir=/var \
--audio-card-list=ac97,es1370,sb16,cs4231a,adlib,gus,hda \
--enable-uname-release=2.6.32 \
# list of system (softmmu) targets, from ./configure
system_targets = x86_64
#system_targets = \
#i386 x86_64 alpha arm cris lm32 m68k microblaze microblazeel \
#mips mipsel mips64 mips64el or32 ppc ppcemb ppc64 sh4 sh4eb \
#sparc sparc64 s390x xtensa xtensaeb unicore32
# qemu-system subpackages
sys_systems = x86
systems = ${sys_systems}
sysarch_x86 = $(filter i386 x86_64,${system_targets})
#sys_systems = arm mips ppc sparc x86
#systems = ${sys_systems} misc
#sysarch_arm = $(filter arm,${system_targets})
#sysarch_mips = $(filter mips mipsel mips64 mips64el,${system_targets})
#sysarch_ppc = $(filter ppc ppc64 ppcemb,${system_targets})
#sysarch_sparc = $(filter sparc sparc64,${system_targets})
#sysarch_x86 = $(filter i386 x86_64,${system_targets})
#sysarch_misc = $(filter-out $(foreach s,${sys_systems},${sysarch_$s}),${system_targets})
ifeq ($(DEB_HOST_ARCH_OS),linux)
# list of linux-user targets, from ./configure
#user_targets = \
# i386 x86_64 alpha arm armeb cris m68k microblaze microblazeel \
#mips mipsel or32 ppc ppc64 ppc64abi32 sh4 sh4eb sparc sparc64 sparc32plus \
# unicore32 s390x
# binfmt linux-user support
all_binfmt_targets = \
$(patsubst debian/binfmts/qemu-%,%,$(wildcard debian/binfmts/qemu-*))
# find which targets needs to be filtered out, which is arch-dependent.
# Drop support for emulating amd64 on i386,
filter_binfmts = $(shell \
case $(DEB_HOST_ARCH) in \
(amd64 | i386) echo i386 x86_64 ;;\
#(arm | armel | armhf) echo arm ;;\
#(mips | mipsel) echo $(DEB_HOST_ARCH) ;;\
# (powerpc) echo ppc ;;\
#(ppc64) echo ppc ppc64 ppc64abi32 ;;\
#(s390x) echo s390x ;;\
#(sparc | sparc64) echo sparc sparc32plus sparc64 ;;\
esac)
binfmt_targets = $(filter-out $(filter_binfmts), $(all_binfmt_targets))
enable_linux_user = --enable-linux-user
else
enable_linux_user =
endif # linux
configure-stamp: configure
dh_testdir
# system build
mkdir -p qemu-build && cd qemu-build && \
../configure ${common_configure_opts} \
--enable-system --disable-user ${enable_linux_user} \
$(shell sh debian/extract-config-opts \
$(DEB_HOST_ARCH_OS)-$(DEB_HOST_ARCH) debian/control) \
$(QEMU_CONFIGURE_OPTIONS)
ifeq ($(DEB_HOST_ARCH_OS),kfreebsd)
# Hack alert. qemu-1.3 still needs this.
# On recent kFreebsd, old USB host API has been removed,
# but qemu did not learn to use new USB API.
# Just do not build USB host support.
sed -i 's/^HOST_USB=bsd/HOST_USB=stub/' \
$(CURDIR)/qemu-build/config-host.mak
endif
ifeq ($(DEB_HOST_ARCH_OS),linux)
# do not use debian/configure-opts here, all optional stuff will be enabled
# automatically, dependencies are already verified in the main build
mkdir -p user-static-build && cd user-static-build && \
../configure ${common_configure_opts} \
--static --disable-system \
--target-list="$(addsuffix -linux-user,${user_targets})"
endif
touch $@
build: build-arch build-indep
build-arch: build-stamp
build-indep: build-stamp
build-stamp: configure-stamp
dh_testdir
# system build
$(MAKE) -C $(CURDIR)/qemu-build
dtc -o qemu-build/pc-bios/bamboo.dtb pc-bios/bamboo.dts
# special case for spapr-rtas.bin file.
# this is an entry point for PPC architecture, which consists of just 5
# processor instructions. We use a pre-compiled pseudo-assembler version
# in debian/spapr-rtas.hex which can be "compiled" using sed magic.
# After "compiling" it this way, we compare with the upstream version,
# it should be the same.
# Use /usr/bin/printf since dash's printf does not understand \xNN.
/usr/bin/printf "$$(sed -n 's|^ .*: \(.*\) .*|\1|p' debian/spapr-rtas.hex | \
tr -d ' \n' | sed 's|\([0-9a-f]\{2\}\)|\\x\1|g')" > \
qemu-build/pc-bios/spapr-rtas.bin
ifeq ($(DEB_HOST_ARCH),powerpc)
$(MAKE) -C qemu-build/pc-bios/spapr-rtas spapr-rtas.bin
cmp qemu-build/pc-bios/spapr-rtas.bin \
qemu-build/pc-bios/spapr-rtas/spapr-rtas.bin
endif
ifeq ($(DEB_HOST_ARCH_OS),linux)
# user-static build
# we use this invocation to build just the binaries
$(MAKE) -C $(CURDIR)/user-static-build $(foreach t,${user_targets},subdir-${t}-linux-user)
endif
touch $@
clean:
dh_testdir
rm -rf $(CURDIR)/*-build/
rm -f $(CURDIR)/*-stamp
find $(CURDIR)/scripts/ -name '*.pyc' -delete || :
dh_clean
define inst-system
for x in postinst prerm; do \
sed 's/@ARCH@/${sysarch_$1}/' debian/qemu-system.$$x-in > debian/qemu-system-$1.$$x.debhelper; \
done
mkdir -p debian/qemu-system-$1/usr/share/man/man1 debian/qemu-system-$1/usr/bin
for t in ${sysarch_$1}; do \
mv debian/tmp/usr/bin/qemu-system-$$t debian/qemu-system-$1/usr/bin/; \
echo ".so man1/qemu.1" > debian/qemu-system-$1/usr/share/man/man1/qemu-system-$$t.1; \
done
echo sysarch:$1=${sysarch_$1} > debian/qemu-system-$1.substvars
echo sysprovides:$1=${addprefix qemu-system-,${filter-out $1,${sysarch_$1}}} | \
sed -e 's/ /, /g' -e 'y/_/-/' >> debian/qemu-system-$1.substvars
endef
install: build-stamp
dh_testdir
dh_testroot
dh_prep
dh_installdirs -a
# system build
$(MAKE) -C $(CURDIR)/qemu-build DESTDIR=$(CURDIR)/debian/tmp install
# qemu-system subpackages
$(foreach s,${systems},$(call inst-system,$s))
ifeq ($(DEB_HOST_ARCH_OS),linux)
# /usr/bin/kvm compat script. This needs some more work for other arches
# How about a manpage for it?
ifneq ($(filter $(DEB_HOST_ARCH),amd64 i386),)
dh_install -pqemu-system-x86 debian/kvm /usr/bin/
mkdir -p debian/qemu-kvm/usr/bin
ln -s kvm debian/qemu-kvm/usr/bin/kvm-spice
ln -s qemu-system-x86_64 debian/qemu-kvm/usr/bin/qemu-system-x86_64-spice
dh_installmodules -pqemu-system-x86
endif
# virtfs-proxy-helper is linux-specific
for f in usr/bin/virtfs-proxy-helper \
usr/share/man/man1/virtfs-proxy-helper.1 ; do \
mkdir -p debian/qemu-system-common/$${f%/*} ; \
mv debian/tmp/$$f debian/qemu-system-common/$$f ; \
done
# qemu-user
mkdir -p debian/qemu-user/usr/bin debian/qemu-user/usr/share/man/man1
for t in ${user_targets}; do \
mv debian/tmp/usr/bin/qemu-$$t \
debian/qemu-user/usr/bin ; \
ln -s qemu-user.1 \
debian/qemu-user/usr/share/man/man1/qemu-$$t.1 ; \
done
# qemu-user-static
mkdir -p debian/qemu-user-static/usr/bin debian/qemu-user-static/usr/share/man/man1
for t in ${user_targets}; do \
cp -p user-static-build/$$t-linux-user/qemu-$$t \
debian/qemu-user-static/usr/bin/qemu-$$t-static ; \
ln -s qemu-user-static.1 \
debian/qemu-user-static/usr/share/man/man1/qemu-$$t-static.1 ; \
done
# binfmt support
for x in postinst prerm; do \
sed 's/@BINFMT_TARGETS@/${all_binfmt_targets}/' \
debian/qemu-user-static.$$x-in > debian/qemu-user-static.$$x.debhelper ; \
done
mkdir -p debian/qemu-user-static/usr/share/binfmts
install -m 644 -t debian/qemu-user-static/usr/share/binfmts/ \
$(addprefix debian/binfmts/qemu-,${binfmt_targets})
endif
# qemu-ifup is arch-specific
install -D debian/qemu-ifup.$(DEB_HOST_ARCH_OS) \
debian/qemu-system-common/etc/qemu-ifup
dh_install --list-missing
dh_installdocs
dh_installchangelogs Changelog
dh_installudev
ifneq ($(filter $(DEB_HOST_ARCH),amd64 i386),)
dh_installinit -pqemu-system-x86 --no-restart-on-upgrade --error-handler=true --name=qemu-kvm
endif
dh_installinit -pqemu-guest-agent
dh_link
dh_strip
dh_compress
dh_fixperms
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary-indep: install
binary-arch: install
binary: install
.PHONY: build clean binary-indep binary-arch binary install
Qemu编译也需要先安装一堆依赖的第三方库:
dev@xxx:~/workroom/qemu-kvm$ sudo apt-get install device-tree-compiler texi2html texinfo libaio-dev libattr1-dev libbluetooth-dev libbrlapi-dev libcap-dev libcap-ng-dev libcurl4-gnutls-dev libfdt-dev libgnutls-dev libncurses5-dev libpulse-dev libsdl1.2-dev libseccomp-dev libxen-dev uuid-dev xfslibs-dev librados-dev librbd-dev
然后安装spice和usbredir,因为我们在qemu的编译选项里加上了对这两个模块的支持:
dev@xxx:~/workroom/ spice $ sudo dpkg –i libspice-server1_0.12.3-0nocelt1_amd64.deb libspice-server-dev_0.12.3-0n0celt1_amd64.deb
dev@xxx:~/workroom/ usbredir$ sudo dpkg –i Libusbredirhost1_0.6-2_amd64.deb, libusbredirhost-dev_0.6-2_amd64.deb, libusbredirparser1_0.6-2_amd64.deb, libusbredirparser-dev_0.6-2_amd64.deb, usbredirserver_0.6-2_amd64.deb
依赖包安装完成后开始编译:
dev@xxx:~/workroom/ qemu-kvm/qemu-1.4.0+dfsg $ sudo debuild
这次编译没那么顺利,报下面的错误:
Unmet build dependencies:libseccomp-dev (>>1.0.0)
明明在安装第三方库中已经包含了libseccomp-dev,为什么还报这个错呢,查一下:
dev@xxx:~/workroom/ qemu-kvm/qemu-1.4.0+dfsg $ sudo dpkg –l | grep libseccomp-dev
结果输出: libseccomp-dev:amd64 0.1.0-1ubuntu1
原来是从ubuntu软件仓库安装的libseccomp-dev版本没有达到qemu-1.4.0的要求,这种情况是常有的。解决的办法是下载libseccomp-dev符合版本要求的源码和编译安装,这也是为什么有时候我们需要自己编译源码来做维护的原因。
https://launchpad.net/ubuntu/+source/libseccomp/1.0.1-2上下载合适的源码,关于libseccomp没有其他依赖,因此不再展开。
继续回来编译qemu-kvm
dev@xxx:~/workroom/ qemu-kvm/qemu-1.4.0+dfsg $ sudo debuild
如无意外,编译完成,照理编译完的qemu安装包在上一层目录下:
先装上这些deb,下面的libvirt编译中需要它们。
dev@xxx:~/workroom/ qemu-kvm $ sudo dpkg –i *.deb
安装时发现还需要安装vgabios, seabios和ipxe-qemu,在此不展开了。