NotePublic/Software/System/Virtualization/Xen/Xen_安装与配置.md

324 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Xen 安装与配置
Xen 分为 Xen Hypervisor、Dom 0 和 Dom U。针对 Xen Hypervisor 需要提供引导配置,针对 Dom U 需要提供虚拟机配置。
## 安装
在 ArchLinux/Manjaro 上通过 yaourt 进行安装。
```sh
yaourt -S xen
```
提示需要 83FE14C957E82BD9 密钥:
```sh
# 注意不要加 sudo因为 root 和每个普通账户的密钥是分别存储的
gpg --recv-keys 83FE14C957E82BD9
gpg --lsign-key 83FE14C957E82BD9
gpg --finger 83FE14C957E82BD9
```
还需要装一些额外的软件包:
```sh
pacman -S seabios ovmf mesa bluez-libs
```
## Grub 引导配置
### Grub 参考引导配置文件
在 ArchLinux/Manjaro 上安装完 Xen 后,在 /etc/grub.d/09_xen 为 Xen Hypervisor 的参考引导配置文件(基于 Grub内容如下
```sh
#!/usr/bin/env bash
##
## grub-mkconfig helper script specific to Arch Linux
## Contributed by "Keshav Amburay" <the ddoott ridikulus ddoott rat aatt geemmayil ddoott ccoomm>
## Updated on 08 February 2014
##
## Script based on do_grub_config() function in Arch Linux Archboot ISO Installer/Setup script
## Some parts taken from /etc/grub.d/10_linux script shipped by GRUB(2) upstream
##
## This script can be freely distributed and/or modified
## under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This script is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## Adapted for use with the xen AUR package, to ensure feature comparity
## Modified by "David Sutton" <kantras - gmail com>
_FUNC_GRUB_FILE_PRESENT() {
[[ -z "${GRUB_PLATFORM}" ]] && GRUB_PLATFORM="x86"
if [[ "${GRUB_PLATFORM}" == "x86" ]]; then
check="--is-x86-linux32"
elif [[ "${GRUB_PLATFORM}" == "i386-xen-pae" ]]; then
check="--is-i386-xen-pae-domu"
elif [[ "${GRUB_PLATFORM}" == "x86_64-xen" ]]; then
check="--is-x86_64-xen-domu"
else
check="--is-${GRUB_PLATFORM}-linux"
fi
case "${GRUB_PLATFORM}" in
x86)
list="$(for i in "${GRUB_ROOT}"/boot/vmlinuz-linux* ; do
if grub_file_is_not_garbage "${i}" && "${grub_file}" ${check} "${i}" ; then echo -n "${i} " ; fi
done)" ;;
*)
list="$(for i in "${GRUB_ROOT}"/boot/vmlinuz-linux* ; do
if grub_file_is_not_garbage "${i}" && "${grub_file}" ${check} "${i}" ; then echo -n "${i} " ; fi
done)" ;;
esac
}
set -e
prefix="/usr"
exec_prefix="${prefix}"
datarootdir="/usr/share"
datadir="${datarootdir}"
sysconfdir="/etc"
. "${datarootdir}/grub/grub-mkconfig_lib"
. "${sysconfdir}/default/grub"
export XEN_HYPERVISOR_CMDLINE="xsave=1"
export XEN_LINUX_CMDLINE="console=tty0"
[[ -r "${sysconfdir}/xen/grub.conf" ]] && . "${sysconfdir}/xen/grub.conf"
[[ -z "${XEN_LINUX_CMDLINE_OVERRIDE}" ]] && XEN_LINUX_CMDLINE_OVERRIDE="0"
export TEXTDOMAIN="grub"
export TEXTDOMAINDIR="${datarootdir}/locale"
CLASS="--class xen --class arch-linux --class arch --class gnu-linux --class gnu --class os"
[[ "${grub_file}" != "" ]] && _FUNC_GRUB_FILE_PRESENT
BOOT_PART_FS_UUID="$(${grub_probe} --target="fs_uuid" "/boot" 2>/dev/null)"
BOOT_PART_HINTS_STRING="$(${grub_probe} --target="hints_string" "/boot" 2>/dev/null || true)"
BOOT_PART_FS="$(${grub_probe} --target="fs" "/boot" 2>/dev/null)"
ROOT_PART_GRUB_DEVICE="$(${grub_probe} --target=device / || true)"
ROOT_PART_FS="$(${grub_probe} --device ${ROOT_PART_GRUB_DEVICE} --target=fs 2> /dev/null || echo "unknown")"
if [[ "${GRUB_LINUX_ROOT_DEVICE}" == "" ]]; then
case "${ROOT_PART_FS}" in
btrfs)
rootsubvol="$(make_system_path_relative_to_its_root /)"
rootsubvol="${rootsubvol#/}"
if [[ "${rootsubvol}" != "" ]]; then
GRUB_LINUX_ROOT_DEVICE="subvol=${rootsubvol}"
fi
;;
zfs)
rpool="$(${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true)"
bootfs="$(make_system_path_relative_to_its_root / | sed -e "s,@$,,")"
GRUB_LINUX_ROOT_DEVICE="ZFS=${rpool}${bootfs}"
;;
esac
if [[ "${GRUB_DEVICE_UUID}" == "" ]] || \
[[ "${GRUB_DISABLE_LINUX_UUID}" == "true" ]] || \
[[ ! -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" ]] || \
uses_abstraction "${GRUB_DEVICE}" lvm ; then
GRUB_LINUX_ROOT_DEVICE="${GRUB_DEVICE}"
else
GRUB_LINUX_ROOT_DEVICE="UUID=${GRUB_DEVICE_UUID}"
fi
fi
[[ "${GRUB_LINUX_PARAMS}" == "" ]] && GRUB_LINUX_PARAMS="${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
if [[ "${XEN_LINUX_CMDLINE_OVERRIDE}" == "0" ]]; then
GRUB_LINUX_PARAMS="${GRUB_LINUX_PARAMS} ${XEN_LINUX_CMDLINE}"
else
GRUB_LINUX_PARAMS="${XEN_LINUX_CMDLINE}"
fi
xen_list=`for i in /boot/xen-*.gz /xen-*.gz ; do
if grub_file_is_not_garbage "$i" ; then echo -n "$i "; fi
done`
while [ "x$xen_list" != "x" ] ; do
xen=`version_find_latest $xen_list`
echo "Found Xen hypervisor image: $xen" >&2
XEN_BASENAME=`basename $xen`
XEN_VERSION=`echo $XEN_BASENAME | sed -e "s,^[^0-9]*-,,g" | sed -e "s,.gz,,g"`
for _KERNEL_ in ${list} ; do
echo "Found linux image: ${_KERNEL_}" >&2
basename="$(basename "${_KERNEL_}")"
dirname="$(dirname "${_KERNEL_}")"
REAL_DIR="$(make_system_path_relative_to_its_root "${dirname}")"
_KERNEL_FILE_="$(echo ${_KERNEL_} | sed 's,/boot/,,g')"
_KERNEL_PKG_="pkg-$(echo ${_KERNEL_FILE_} | sed 's,vmlinuz-,,g')"
_INITRAMFS_="${_KERNEL_FILE_/vmlinuz-/initramfs-}.img"
if [[ -e "/boot/${_INITRAMFS_}" ]]; then
echo "Found initramfs image: /boot/${_INITRAMFS_}" >&2
cat << EOF
menuentry "Xen ${XEN_VERSION} / Arch Linux ${_KERNEL_PKG_} kernel" ${CLASS} {
$(save_default_entry)
if [ x\$feature_all_video_module = xy ]; then
insmod all_video
fi
set gfxpayload=keep
insmod ${BOOT_PART_FS}
if [ x\$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root ${BOOT_PART_HINTS_STRING} ${BOOT_PART_FS_UUID}
else
search --no-floppy --fs-uuid --set=root ${BOOT_PART_FS_UUID}
fi
echo '$(printf "Loading Xen %s ..." ${XEN_VERSION})'
multiboot2 ${REAL_DIR}/${XEN_BASENAME} ${XEN_HYPERVISOR_CMDLINE}
echo 'Loading Arch Linux ${_KERNEL_PKG_} kernel ...'
module2 ${REAL_DIR}/${_KERNEL_FILE_} root=${GRUB_LINUX_ROOT_DEVICE} rw ${GRUB_LINUX_PARAMS}
echo 'Loading Arch Linux ${_KERNEL_PKG_} kernel initramfs ...'
module2 ${REAL_DIR}/${_INITRAMFS_}
}
EOF
fi
_INITRAMFS_FALLBACK_="${_KERNEL_FILE_/vmlinuz-/initramfs-}-fallback.img"
if [[ -e "/boot/${_INITRAMFS_FALLBACK_}" ]]; then
echo "Found fallback initramfs image: /boot/${_INITRAMFS_FALLBACK_}" >&2
cat << EOF
menuentry "Xen ${XEN_VERSION} / Arch Linux ${_KERNEL_PKG_} kernel (fallback initramfs)" ${CLASS} {
$(save_default_entry)
if [ x\$feature_all_video_module = xy ]; then
insmod all_video
fi
set gfxpayload=keep
insmod ${BOOT_PART_FS}
if [ x\$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root ${BOOT_PART_HINTS_STRING} ${BOOT_PART_FS_UUID}
else
search --no-floppy --fs-uuid --set=root ${BOOT_PART_FS_UUID}
fi
echo '$(printf "Loading Xen %s ..." ${XEN_VERSION})'
multiboot2 ${REAL_DIR}/${XEN_BASENAME} ${XEN_HYPERVISOR_CMDLINE}
echo 'Loading Arch Linux ${_KERNEL_PKG_} kernel ...'
module2 ${REAL_DIR}/${_KERNEL_FILE_} root=${GRUB_LINUX_ROOT_DEVICE} rw ${GRUB_LINUX_PARAMS}
echo 'Loading Arch Linux ${_KERNEL_PKG_} kernel fallback initramfs ...'
module2 ${REAL_DIR}/${_INITRAMFS_FALLBACK_}
}
EOF
fi
if [[ ! -e "/boot/${_INITRAMFS_}" ]] && [[ ! -e "/boot/${_INITRAMFS_FALLBACK_}" ]]; then
cat << EOF
menuentry "Xen ${XEN_VERSION} / Arch Linux ${_KERNEL_PKG_} kernel (no initramfs)" ${CLASS} {
$(save_default_entry)
if [ x\$feature_all_video_module = xy ]; then
insmod all_video
fi
set gfxpayload=keep
insmod ${BOOT_PART_FS}
if [ x\$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root ${BOOT_PART_HINTS_STRING} ${BOOT_PART_FS_UUID}
else
search --no-floppy --fs-uuid --set=root ${BOOT_PART_FS_UUID}
fi
echo '$(printf "Loading Xen %s ..." ${XEN_VERSION})'
multiboot2 ${REAL_DIR}/${XEN_BASENAME} ${XEN_HYPERVISOR_CMDLINE}
echo 'Loading Arch Linux ${_KERNEL_PKG_} kernel ...'
module2 ${REAL_DIR}/${_KERNEL_FILE_} root=${GRUB_LINUX_ROOT_DEVICE} rw ${GRUB_LINUX_PARAMS}
}
EOF
fi
done
xen_list=`echo $xen_list | tr ' ' '\n' | grep -vx $xen | tr '\n' ' '`
done
```
### 一个简化的 Grub 配置参考
一个简化的 Grup 引导配置文件如下,其中 xen-4.12.1.gz 为 Xen Hypervisorvmlinuz-4.9-x86_64 为支持 Xen 的 Dom 0 Linux Kernelinitramfs-4.9-x86_64.img 为 RAM Disk。注意当前的根为“/boot”而非“/”。"xsave=1" "dom0_max_vcpus=1" "dom0_mem=1024M" 为 Xen Hypervisorvmlinuz 的 Command Line Options。root=UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx rw quiet udev.log_priority=3 为 Dom 0 Kernel Command Line Options。
```sh
menuentry "Xen / Arch Linux kernel" --class manjaro --class gnu-linux --class gnu --class os {
savedefault
load_video
set gfxpayload=keep
insmod gzio
insmod part_msdos
insmod ext2
set root='hd0,msdos1'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
else
search --no-floppy --fs-uuid --set=root xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
fi
multiboot2 /xen-4.12.1.gz "xsave=1" "dom0_max_vcpus=1" "dom0_mem=1024M"
echo 'Loading kernel ...'
module2 /vmlinuz-4.9-x86_64 root=UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx rw quiet udev.log_priority=3
echo 'Loading initial ramdisk ...'
module2 /initramfs-4.9-x86_64.img
}
```
## Systemd-boot 引导配置
Systemd-boot 无法直接引导 xen-4.12.1.gz并且配置其参数。但是 Systemd-boot 可以引导 efi 文件,因此可以先引导 xen-4.12.1.efi再由 xen-4.12.1.efi 引导 Dom0 内核进行启动。xen-4.12.1.efi 需要一个配置文件用于配置 Dom0。但在此之前先要编写 Systemd-boot 的 entry 文件 /boot/loader/entries/10-xen.conf 文件,用于引导 xen-4.12.1.efi
```sh
title Xen Hypervisor
efi /xen-4.12.1.efi
```
之后在 /boot 目录下创建 xen-4.12.1.cfg 文件用于配置 Dom0
```sh
[global]
default=xen
[xen]
options=loglvl=all noreboot=true reboot=no dom0_max_vcpus=3 dom0_mem=6000M
ucode=intel-ucode.img
kernel=vmlinuz-5.3-x86_64 root=PARTUUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx rw
ramdisk=initramfs-5.3-x86_64.img
```
xen-4.12.1.efi 会按照一定规则查找 cfg 文件,首先会查找与自身同名但是扩展名为 cfg 的文件,最后会查找 xen.cfg 文件。更详细的规则可以参考官方帮助。
## DomU
DomU 的使用和配置请参考 [Xen DomU 配置与使用](Xen_DomU_配置与使用.md)
## 参考资料
<https://xenbits.xen.org/docs/unstable/misc/efi.html>
<https://wiki.archlinux.org/index.php/Xen>