diff --git a/classes/virt_networking.bbclass b/classes/virt_networking.bbclass new file mode 100644 index 00000000..e92e1de5 --- /dev/null +++ b/classes/virt_networking.bbclass @@ -0,0 +1,26 @@ +# Similarly to the cni_networking.bbclass this class should be +# inherted by recipes to produce a package that contains their +# desired networking configuration. +# +# Currently only systemd networking is supported, but this will +# be extended in the future +# +# By simply specifying the configuration / networking files, +# they will be package and then eventually installed to the +# correct target location. +# +PACKAGES:prepend = "${PN}-net-conf " +FILES:${PN}-net-conf = "${sysconfdir}/systemd/network/*" + +do_install:append() { + if [ -z "${VIRT_NETWORKING_FILES}" ]; then + bbfatal "virt-networking was inherited, but no networking configuration was provided via VIRT_NETWORKING_FILES" + fi + + # TODO: possibily make the systemd configuration conditional on the init manager + install -d "${D}/${sysconfdir}/systemd/network/" + for f in ${VIRT_NETWORKING_FILES}; do + conf_name="$(basename $f)" + install -D -m 0644 "$f" "${D}/${sysconfdir}/systemd/network/$conf_name" + done +} diff --git a/recipes-extended/images/xen-guest-image-minimal.bb b/recipes-extended/images/xen-guest-image-minimal.bb index fced7639..76f320e4 100644 --- a/recipes-extended/images/xen-guest-image-minimal.bb +++ b/recipes-extended/images/xen-guest-image-minimal.bb @@ -1,6 +1,7 @@ DESCRIPTION = "A Xen guest image." -inherit core-image features_check +inherit core-image features_check deploy +inherit kernel-artifact-names IMAGE_INSTALL += " \ packagegroup-core-boot \ @@ -23,3 +24,28 @@ LICENSE = "MIT" # Send console messages to xen console APPEND += "console=hvc0" + +IMAGE_FSTYPES = "tar.bz2 ext4 ext4.qcow2" + +XEN_GUEST_AUTO_BUNDLE ?= "" + +# When a xen-guest-image-minimal is built with the +# XEN_GUEST_AUTO_BUNDLE varaible set to True, a configuration file for +# automatic guest bundling will be generated and the guest bundled +# automatically when a xen host image is built. +do_deploy() { + if [ -n "${XEN_GUEST_AUTO_BUNDLE}" ]; then + outname="xen-guest-bundle-${IMAGE_BASENAME}${IMAGE_MACHINE_SUFFIX}-${IMAGE_VERSION_SUFFIX}.cfg" +cat <>${DEPLOYDIR}/$outname +name = "xen-guest" +memory = 512 +vcpus = 1 +disk = ['file:${IMAGE_LINK_NAME}.ext4,xvda,rw'] +vif = ['bridge=xenbr0'] +kernel = "${KERNEL_IMAGETYPE}" +extra = "root=/dev/xvda ro ip=dhcp" +EOF + fi +} + +addtask deploy after do_compile diff --git a/recipes-extended/images/xen-image-minimal.bb b/recipes-extended/images/xen-image-minimal.bb index e6fa93ca..866212ed 100644 --- a/recipes-extended/images/xen-image-minimal.bb +++ b/recipes-extended/images/xen-image-minimal.bb @@ -1,9 +1,14 @@ DESCRIPTION = "A minimal xen image" +inherit features_check + +REQUIRED_DISTRO_FEATURES ?= "xen systemd" + INITRD_IMAGE = "core-image-minimal-initramfs" XEN_KERNEL_MODULES ?= "kernel-module-xen-blkback kernel-module-xen-gntalloc \ kernel-module-xen-gntdev kernel-module-xen-netback kernel-module-xen-wdt \ + kernel-module-xt-comment kernel-module-xt-masquerade \ ${@bb.utils.contains('MACHINE_FEATURES', 'pci', "${XEN_PCIBACK_MODULE}", '', d)} \ ${@bb.utils.contains('MACHINE_FEATURES', 'acpi', '${XEN_ACPI_PROCESSOR_MODULE}', '', d)} \ " @@ -16,6 +21,7 @@ IMAGE_INSTALL += " \ qemu \ kernel-image \ kernel-vmlinux \ + rsync \ " # The hypervisor may not be within the dom0 filesystem image but at least @@ -44,14 +50,6 @@ QB_QEMU_CLASSES = "" QB_QEMU_CLASSES:qemuall = "qemuboot-xen-defaults qemuboot-xen-dtb qemuboot-testimage-network" inherit ${QB_QEMU_CLASSES} -do_check_xen_state() { - if [ "${@bb.utils.contains('DISTRO_FEATURES', 'xen', ' yes', 'no', d)}" = "no" ]; then - die "DISTRO_FEATURES does not contain 'xen'" - fi -} - -addtask check_xen_state before do_rootfs - # note: this may be unused, see the wic plugin syslinux_iso_populate:append() { install -m 0444 ${STAGING_DATADIR}/syslinux/libcom32.c32 ${ISODIR}${ISOLINUXDIR} @@ -88,6 +86,168 @@ build_syslinux_cfg () { echo " APPEND /xen.gz ${SYSLINUX_XEN_ARGS} --- /vmlinuz ${SYSLINUX_KERNEL_ARGS} --- /initrd" >> ${SYSLINUX_CFG} } +# Function to parse the config file and get values for specific keys +get_config_value() { + config_file="$1" + key="$2" + line=$(grep -w "$key" $config_file) + value=$(echo "$line" | cut -d '=' -f 2-) + # Remove quotes, leading/trailing whitespace, and content after the first comma + echo "${value#*=}" | sed "s/'//g; s/^\s*|\s*$//g; s/\[//g;s/\"//g;s/^ *//g;" | cut -d ',' -f 1 +} + +generate_guest_config() { + name=$1 + kernel=$2 + disk=$3 + outname=$name.cfg + + cat <${DEPLOY_DIR_IMAGE}/$outname +name = "$name" +memory = 512 +vcpus = 1 +disk = ['file:$disk,xvda,rw'] +vif = ['bridge=xenbr0'] +kernel = "$kernel" +extra = "root=/dev/xvda ro ip=dhcp" +EOF +} + +# Guests can be bundled automatically through the following mechanisms: +# +# - via the variable XEN_BUNDLED_GUESTS +# - via a xen configuration file in the deploy directory of the format +# xen-guest-bundle-*.cfg +# +# The guests can be built via OE, or be 3rd party guests. They just +# must be in the deploy directory so they can be copied into the rootfs +# of the xen host image +# +# Type 1) XEN_BUNDLED_GUESTS +# +# If XEN_BUNDLED_GUESTS is used, it is simply a colon separated list of +# rootfs:kernels. Normal variable rules apply, so it can be set in a +# local.conf, or in a bbappend to the image recipe. +# +# An example would be: +# +# XEN_BUNDLED_GUESTS = "xen-guest-image-minimal-qemuarm64.rootfs.ext4:Image" +# +# These point at symlinks created in the image deploy directory, or they +# can be specific images/kernels without the symlink. +# +# Type 2) A Xen guest configuration file +# +# If xen guest configuration files are found in the deploy directories +# the kernel and disk information contained within them will be processed +# and modified for the xen host. The kernel and guest image will be +# copied to the appropriate location, and the config made to match. +# +# These files following the naming convention: xen-guest-bundle*.cfg +# +# Guests of type #1 generate a configuration file that is picked up as +# type #2. +# +# An example config file follows: +# +## name = "xen-guest" +## memory = 512 +## vcpus = 1 +## disk = ['file:xen-guest-image-minimal-qemuarm64.rootfs.ext4,xvda,rw'] +## vif = ['bridge=xenbr0'] +## kernel = "Image" +## extra = "root=/dev/xvda ro console=hvc0 ip=dhcp" +# +# It should also be noted that when a xen-guest-image-minimal is built +# with the XEN_GUEST_AUTO_BUNDLE varaible set to True, a configuration +# file for type #2 will be generated and the guest bundled automatically +# when the host image is built. +# +# kernel and rootfs are copied to the target in /var/lib/xen/images/ +# +# configuration files are copied to: /etc/xen +# +# Guests can be launched after boot with: xl create -c /etc/xen/ +# +bundle_xen_guests() { + set -e + + if [ -n "${XEN_BUNDLED_GUESTS}" ]; then + echo "Processing Xen bundled guests variable: ${XEN_BUNDLED_GUESTS}" + # these are a colon separated list of rootfs:kernel + count=1 + for g in ${XEN_BUNDLED_GUESTS}; do + echo "Guest line: $g" + rootfs=$(echo "$g" | cut -d":" -f1) + kernel=$(echo "$g" | cut -d":" -f2) + name="xen-guest-bundle-$count" + + if ! [ -e ${DEPLOY_DIR_IMAGE}/$rootfs ]; then + echo "rootfs '${DEPLOY_DIR_IMAGE}/$rootfs' not found, skipping ...." + continue + fi + if ! [ -e ${DEPLOY_DIR_IMAGE}/$kernel ]; then + echo "kernel '${DEPLOY_DIR_IMAGE}/$kernel' not found, skipping ...." + continue + fi + + generate_guest_config $name $kernel $rootfs + + count=$(expr $count + 1) + done + fi + + echo ls ${DEPLOY_DIR_IMAGE}/xen-guest-bundle*.cfg + ls ${DEPLOY_DIR_IMAGE}/xen-guest-bundle*.cfg >/dev/null 2>/dev/null + if [ $? -eq 0 ]; then + for guest_cfg in $(ls ${DEPLOY_DIR_IMAGE}/xen-guest-bundle*.cfg); do + echo "Bundling guest: $guest_cfg" + + CONFIG_FILE_BASE=$(basename $guest_cfg .cfg) + CONFIG_FILE="${DEPLOY_DIR_IMAGE}/$CONFIG_FILE_BASE.cfg" + DEST_DIR="${IMAGE_ROOTFS}/var/lib/xen/images" + MODIFIED_CONFIG_FILE="${DEPLOY_DIR_IMAGE}/$CONFIG_FILE_BASE-modified.cfg" + + # Extract values from the configuration file + DISK_ORIG=$(get_config_value $CONFIG_FILE "disk" | sed 's/file://g') + DISK=$(readlink -f ${DEPLOY_DIR_IMAGE}/$DISK_ORIG) + DISK_NAME=$(basename $DISK) + KERNEL_ORIG=$(get_config_value $CONFIG_FILE "kernel") + KERNEL=$(readlink -f ${DEPLOY_DIR_IMAGE}/$KERNEL_ORIG) + KERNEL_NAME=$(basename $KERNEL) + + if [ -z "$DISK" ]; then + echo "rootfs '$DISK' not found, skipping ...." + continue + fi + if [ -z "$KERNEL" ]; then + echo "kernel '$KERNEL' not found, skipping ...." + continue + fi + + mkdir -p "$DEST_DIR" + # Copy the disk and kernel to the destination directory + echo "Copying disk and kernel files..." + echo cp "$DISK" "$DEST_DIR" + echo cp "$KERNEL" "$DEST_DIR" + cp "$DISK" "$DEST_DIR" + cp "$KERNEL" "$DEST_DIR" + + # Create a modified config file with updated paths + sed -E \ + -e "s#^(disk = \[)[^,]+#\1'file:/var/lib/xen/images/$DISK_NAME#" \ + -e "s#^(kernel = )\"[^\"]+\"#\1\"/var/lib/xen/images/$KERNEL_NAME\"#" \ + "$CONFIG_FILE" > "$MODIFIED_CONFIG_FILE" + + mkdir -p ${IMAGE_ROOTFS}/etc/xen + cp $MODIFIED_CONFIG_FILE ${IMAGE_ROOTFS}/etc/xen/$CONFIG_FILE_BASE.cfg + rm -f $MODIFIED_CONFIG_FILE + done + fi + # exit 1 +} +ROOTFS_POSTPROCESS_COMMAND += "bundle_xen_guests;" + # Enable runqemu. eg: runqemu xen-image-minimal nographic slirp WKS_FILE:x86-64 = "directdisk-xen.wks" WKS_FILE_DEPENDS_DEFAULT:x86-64 = "syslinux-native" @@ -107,3 +267,8 @@ do_image_wic[depends] += "xen:do_deploy" # and so does the emulated e1000 -- choose according to the network device # drivers that are present in your dom0 Linux kernel. To switch to e1000: # QB_NETWORK_DEVICE = "-device e1000,netdev=net0,mac=@MAC@" + + +IMAGE_ROOTFS_SIZE = "8192" +# we always need extra space to install VMs, so add 2GB +IMAGE_ROOTFS_EXTRA_SPACE = "2000000" diff --git a/recipes-extended/xen/files/10-ether.network b/recipes-extended/xen/files/10-ether.network new file mode 100644 index 00000000..8d27ca92 --- /dev/null +++ b/recipes-extended/xen/files/10-ether.network @@ -0,0 +1,5 @@ +[Match] +Type=ether + +[Network] +Bridge=xenbr0 diff --git a/recipes-extended/xen/files/10-xenbr0.netdev b/recipes-extended/xen/files/10-xenbr0.netdev new file mode 100644 index 00000000..ec45879f --- /dev/null +++ b/recipes-extended/xen/files/10-xenbr0.netdev @@ -0,0 +1,3 @@ +[NetDev] +Name=xenbr0 +Kind=bridge diff --git a/recipes-extended/xen/files/10-xenbr0.network b/recipes-extended/xen/files/10-xenbr0.network new file mode 100644 index 00000000..1e10c3eb --- /dev/null +++ b/recipes-extended/xen/files/10-xenbr0.network @@ -0,0 +1,5 @@ +[Match] +Name=xenbr0 + +[Network] +DHCP=yes diff --git a/recipes-extended/xen/xen-tools.inc b/recipes-extended/xen/xen-tools.inc index 35dbb493..fba10b04 100644 --- a/recipes-extended/xen/xen-tools.inc +++ b/recipes-extended/xen/xen-tools.inc @@ -6,6 +6,15 @@ COMPATIBLE_HOST = 'i686-.*-linux|(x86_64.*).*-linux|aarch64.*-linux|arm-.*-linux inherit setuptools3 update-rc.d systemd deploy require xen-blktap.inc +SRC_URI += "file://10-ether.network \ + file://10-xenbr0.netdev \ + file://10-xenbr0.network" + +VIRT_NETWORKING_FILES = "${UNPACKDIR}/10-ether.network \ + ${UNPACKDIR}/10-xenbr0.netdev \ + ${UNPACKDIR}/10-xenbr0.network" +inherit virt_networking + QEMU_SYSTEM ?= "qemu-system-i386" QEMU_SYSTEM_RDEPENDS ?= "${QEMU_SYSTEM} qemu-firmware" @@ -30,6 +39,7 @@ RDEPENDS:${PN} = "\ virtual-xenstored \ ${PN}-xl \ ${QEMU_SYSTEM_RDEPENDS} \ + ${PN}-net-conf \ " RDEPENDS:${PN}-dev = ""