diff options
author | takeshi_hoshina <takeshi_hoshina@mail.toyota.co.jp> | 2020-11-02 11:07:33 +0900 |
---|---|---|
committer | takeshi_hoshina <takeshi_hoshina@mail.toyota.co.jp> | 2020-11-02 11:07:33 +0900 |
commit | 1c7d6584a7811b7785ae5c1e378f14b5ba0971cf (patch) | |
tree | cd70a267a5ef105ba32f200aa088e281fbd85747 /bsp/meta-arm/meta-arm-autonomy/recipes-extended | |
parent | 4204309872da5cb401cbb2729d9e2d4869a87f42 (diff) |
basesystem-jjsandbox/ToshikazuOhiwa/master-jj
recipes
Diffstat (limited to 'bsp/meta-arm/meta-arm-autonomy/recipes-extended')
14 files changed, 1979 insertions, 0 deletions
diff --git a/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xen-devicetree/files/xen.dtsi.in b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xen-devicetree/files/xen.dtsi.in new file mode 100644 index 00000000..42d12fae --- /dev/null +++ b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xen-devicetree/files/xen.dtsi.in @@ -0,0 +1,17 @@ +/ { + chosen { + xen,dom0-bootargs = "###XEN_DOM0_BOOTARGS###"; + xen,xen-bootargs = "###XEN_XEN_BOOTARGS###"; + + modules { + #size-cells = <0x00000001>; + #address-cells = <0x00000001>; + + module@0 { + reg = <###XEN_DOM0_ADDR### ###XEN_DOM0_SIZE###>; + compatible = "multiboot,module"; + }; + }; + }; +}; + diff --git a/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xen-devicetree/xen-devicetree.bb b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xen-devicetree/xen-devicetree.bb new file mode 100644 index 00000000..cef5f79e --- /dev/null +++ b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xen-devicetree/xen-devicetree.bb @@ -0,0 +1,72 @@ +# This recipe can be used to modify one or several DTBS to add +# entries required to declare and boot Linux as Dom0 from Xen + +SRC_URI = "file://xen.dtsi.in" + +LICENSE = "MIT" +LIC_FILES_CHKSUM = "\ + file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302 \ + " + +S = "${WORKDIR}" + +DESCRIPTION = "Add entries in DTB for Xen and Dom0" + +# Please refer to documentation/xen-devicetree.md for documentation on those +# parameters +XEN_DEVICETREE_DEPEND ?= "virtual/kernel:do_deploy" +XEN_DEVICETREE_DTBS ?= "${KERNEL_DEVICETREE}" +XEN_DEVICETREE_XEN_BOOTARGS ?= "noreboot dom0_mem=${XEN_DEVICETREE_DOM0_MEM}" +XEN_DEVICETREE_DOM0_MEM ?= "1024M" +XEN_DEVICETREE_DOM0_BOOTARGS ?= "console=hvc0 earlycon=xen" +XEN_DEVICETREE_DOM0_ADDR ?= "0x80080000" +XEN_DEVICETREE_DOM0_SIZE ?= "0x01000000" +XEN_DEVICETREE_DTSI_MERGE ?= "xen.dtsi" + +# Our package does not generate any package for the rootfs but contributes to +# deploy +inherit nopackages deploy + +DEPENDS += "dtc-native" + +do_configure[noexec] = "1" +do_compile[noexec] = "1" +do_install[noexec] = "1" + +do_deploy() { + if [ ! -f ${WORKDIR}/xen.dtsi.in ]; then + die "xen.dtsi.in does not exist" + fi + cat ${WORKDIR}/xen.dtsi.in \ + | sed -e "s,###XEN_DOM0_BOOTARGS###,${XEN_DEVICETREE_DOM0_BOOTARGS}," \ + | sed -e "s,###XEN_XEN_BOOTARGS###,${XEN_DEVICETREE_XEN_BOOTARGS}," \ + | sed -e "s,###XEN_DOM0_ADDR###,${XEN_DEVICETREE_DOM0_ADDR}," \ + | sed -e "s,###XEN_DOM0_SIZE###,${XEN_DEVICETREE_DOM0_SIZE}," \ + > ${WORKDIR}/xen.dtsi + + # Generate final dtbs + for dtbf in ${XEN_DEVICETREE_DTBS}; do + rdtb=`basename $dtbf` + if [ ! -f ${DEPLOY_DIR_IMAGE}/$rdtb ]; then + die "Wrong file in XEN_DEVICETREE_DTBS: ${DEPLOY_DIR_IMAGE}/$rdtb does not exist" + fi + dtc -I dtb -O dts -o ${WORKDIR}/dom0-linux.dts ${DEPLOY_DIR_IMAGE}/$rdtb + + # Add external includes + for inc in ${XEN_DEVICETREE_DTSI_MERGE}; do + if [ ! -f ${WORKDIR}/${inc} ]; then + die "Wrong file in XEN_DEVICETREE_DTSI_MERGE: ${WORKDIR}/${inc} does not exist" + fi + echo "/include/ \"$inc\"" >> ${WORKDIR}/dom0-linux.dts + done + + rdtbnoextn=`basename $dtbf ".dtb"` + dtc -I dts -O dtb \ + -o ${WORKDIR}/${rdtbnoextn}-xen.dtb ${WORKDIR}/dom0-linux.dts + install -m 644 ${rdtbnoextn}-xen.dtb ${DEPLOYDIR}/. + done +} +do_deploy[depends] += "${XEN_DEVICETREE_DEPEND}" + +addtask deploy after do_install + diff --git a/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xen/xen_%.bbappend b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xen/xen_%.bbappend new file mode 100644 index 00000000..846d2442 --- /dev/null +++ b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xen/xen_%.bbappend @@ -0,0 +1,14 @@ +# +# Define early console based on board parameters +# + +XEN_CONFIG_EARLY_PRINTK ??= "disable" + +EXTRA_OEMAKE += "${@bb.utils.contains('XEN_CONFIG_EARLY_PRINTK', 'disable', \ + '', ' CONFIG_DEBUG=y CONFIG_EARLY_PRINTK=${XEN_CONFIG_EARLY_PRINTK}',d)}" + +# Make Xen machine specific +# This ensures that sstate is properly handled and that each machine can have +# its own configuration +PACKAGE_ARCH = "${MACHINE_ARCH}" + diff --git a/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/network-bridge.sh.in b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/network-bridge.sh.in new file mode 100755 index 00000000..2a360964 --- /dev/null +++ b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/network-bridge.sh.in @@ -0,0 +1,15 @@ +#!/bin/sh +# This script is setting up a virtual network interface connected to the +# xenguest-network-bridge if NETWORK_BRIDGE is set to 1 in the guest params + +guestname="${1}" + +BRIDGE_NAME="###BRIDGE_NAME###" + +# get guest parameters +. ./params.cfg + +if [ "${NETWORK_BRIDGE:-}" = "1" ]; then + echo "vif = ['${BRIDGE_NAME}']" >> ${guestname}.cfg +fi + diff --git a/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-init b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-init new file mode 100755 index 00000000..9563d2fc --- /dev/null +++ b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-init @@ -0,0 +1,85 @@ +#!/bin/bash +# +# xenguest Init Script to start and stop xenguests during boot +# + +XENGUEST_CONF_BASE="/etc/xenguest" + +if [ ! -f ${XENGUEST_CONF_BASE}/xenguest-manager.conf ]; then + echo "No xenguest manager configuration !!" + exit 1 +fi + +source ${XENGUEST_CONF_BASE}/xenguest-manager.conf + +# Create guest list +guestlist=$(/usr/bin/xenguest-manager list) + +# Unconfigured guests + +case "$1" in + start) + echo "Starting xenguest" + + # Create unconfigured guests + if [ -d ${XENGUEST_GUEST_DIR} ]; then + for f in $(find ${XENGUEST_GUEST_DIR} -name "*.xenguest" \ + -exec basename {} .xenguest \;); do + if [ ! -f ${XENGUEST_CONF_BASE}/guests/${f}/guest.cfg ]; then + # Check if this guest should be auto booted + autoboot=$(/usr/bin/xenguest-mkimage dump-paramsconfig \ + ${XENGUEST_GUEST_DIR}/${f}.xenguest | \ + grep GUEST_AUTOBOOT | sed -e "s,.*=,," | tr -d '"') + if [ "$autoboot" = "0" ]; then + echo "Do not create $f, autoboot disabled" + else + /usr/bin/xenguest-manager create \ + ${XENGUEST_GUEST_DIR}/${f}.xenguest + # Update guestlist + if [ $? -eq 0 ]; then + guestlist="${guestlist} ${f}" + fi + fi + fi + done + fi + if [ -n "${guestlist}" ]; then + for f in ${guestlist}; do + GUEST_AUTOBOOT="1" + if [ -f ${XENGUEST_CONF_BASE}/guests/${f}/params.cfg ]; then + source ${XENGUEST_CONF_BASE}/guests/${f}/params.cfg + fi + if [ "${GUEST_AUTOBOOT}" = "1" ]; then + /usr/bin/xenguest-manager start ${f} + fi + done + else + echo "No guest configured" + fi + ;; + status) + true + ;; + stop) + echo "Stopping xenguest" + for f in ${guestlist}; do + /usr/bin/xenguest-manager stop ${f} + done + ;; + reload) + echo >&2 'Reload not available; use force-reload'; exit 1 + ;; + force-reload|restart) + echo "Restarting xenguest" + $0 stop + $0 start + ;; + *) + # do not advertise unreasonable commands that there is no reason + # to use with this device + echo $"Usage: $0 {start|stop|status|restart|force-reload}" + exit 1 +esac + +exit $? + diff --git a/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-manager b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-manager new file mode 100755 index 00000000..99975a24 --- /dev/null +++ b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-manager @@ -0,0 +1,665 @@ +#!/bin/bash +# This script manages xenguest +# +set -u +this="$0" + +XENGUEST_CONF_BASE="/etc/xenguest" +LOGFILE="/var/log/xenguest" + +if [ ! -f ${XENGUEST_CONF_BASE}/xenguest-manager.conf ]; then + echo "Cannot find xenguest manager configuration" + exit 1 +fi + +# Following variables must be set in configuration: +# XENGUEST_VOLUME_DEVICE: device to use for lvm +# XENGUEST_VOLUME_NAME: lvm volume name to create on device +source ${XENGUEST_CONF_BASE}/xenguest-manager.conf + +PREF="xenguest:" + +function usage() { + cat <<EOF +Usage $this ACTION [OPTIONS] + +with ACTION being one of: + help + Display this help + + create GUESTFILE [GUESTNAME] + Create a guest using xenguest image GUESTFILE and name it GUESTNAME. + This will extract and configure the guest and will also create the guest + disk if guest has one configured. + GUESTNAME is set to the basename of GUESTFILE if unspecified. + GUESTNAME guest must not exist + + remove GUESTNAME + Remove GUESTNAME and destroy its disk (if it has one) + + start GUESTNAME + Start guest GUESTNAME + + stop|shutdown GUESTNAME + Stop guest GUESTNAME (send stop signal and let it shutdown normally) + + kill|destroy GUESTNAME + Kill guest GUESTNAME (stop directly the guest without signaling it) + + list + List configured guests + + status + List guests and their current status (running or stopped) +EOF +} + +function xenguest_volume_init() +{ + if [ -z "${XENGUEST_VOLUME_DEVICE:-}" -o \ + ! -b ${XENGUEST_VOLUME_DEVICE:-} ]; then + echo "${PREF} Invalid volume device in configuration: ${XENGUEST_VOLUME_DEVICE:-}" + exit 1 + fi + + if [ -z "${XENGUEST_VOLUME_NAME:-}" ]; then + echo "${PREF} No volume name in configuration, using vg-xen..." + XENGUEST_VOLUME_NAME="vg-xen" + fi + + pvs ${XENGUEST_VOLUME_DEVICE} > /dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Initialize lvm on ${XENGUEST_VOLUME_DEVICE}" + echo "pvcreate -f ${XENGUEST_VOLUME_DEVICE}" >> ${LOGFILE} 2>&1 + pvcreate -f ${XENGUEST_VOLUME_DEVICE} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error" + exit 1 + fi + fi + vgs ${XENGUEST_VOLUME_NAME} > /dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Create ${XENGUEST_VOLUME_NAME} volume" + echo "vgcreate ${XENGUEST_VOLUME_NAME} ${XENGUEST_VOLUME_DEVICE}" \ + >> ${LOGFILE} 2>&1 + vgcreate ${XENGUEST_VOLUME_NAME} ${XENGUEST_VOLUME_DEVICE} \ + >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error" + exit 1 + fi + fi +} + +# Detach a disk we attached to xen +function xenguest_detach_disk() +{ + echo "xl block-detach 0 \$\(xl block-list 0 | " \ + "grep \"domain/0\" | awk '{print \$1}'\)" \ + >> ${LOGFILE} 2>&1 + xl block-detach 0 $(xl block-list 0 | \ + grep "domain/0" | awk '{print $1}') \ + >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error detaching partition ${part}" + exit 1 + fi +} + +function xenguest_disk_init() +{ + guestname="$1" + guestfile="$2" + devname="/dev/${XENGUEST_VOLUME_NAME}/${guestname}" + + source ${XENGUEST_CONF_BASE}/guests/${guestname}/disk.cfg + + if [ ${DISK_SIZE:-0} -eq 0 ]; then + echo "${PREF} No disk for ${guestname}" + return + fi + + echo "${PREF} Create ${guestname} disk" + + # Init our volume + xenguest_volume_init + + echo "${PREF} Create hard drive for ${guestname}" + + + # Remove volume if it already exist + echo "lvs ${XENGUEST_VOLUME_NAME}/${guestname}" >> ${LOGFILE} 2>&1 + lvs ${XENGUEST_VOLUME_NAME}/${guestname} >> ${LOGFILE} 2>&1 + if [ $? -eq 0 ]; then + echo "lvremove -y ${devname}" >> ${LOGFILE} 2>&1 + lvremove -y ${devname} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error removing volume ${guestname}" + exit 1 + fi + fi + + # Create volume + echo "lvcreate -y -L ${DISK_SIZE}G -n ${guestname} ${XENGUEST_VOLUME_NAME}" \ + >> ${LOGFILE} 2>&1 + lvcreate -y -L ${DISK_SIZE}G -n ${guestname} ${XENGUEST_VOLUME_NAME} \ + >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error creating volume ${guestname}" + exit 1 + fi + + # Add partition table + echo "parted -s ${devname} mklabel msdos" >> ${LOGFILE} 2>&1 + parted -s ${devname} mklabel msdos >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error creating partition table on ${guestname}" + exit 1 + fi + + # Setup disk name in xen configuration + echo "xenguest-mkimage update ${XENGUEST_CONF_BASE}/guests/${guestname}" \ + "--xen-disk=${devname}" >> ${LOGFILE} 2>&1 + xenguest-mkimage update ${XENGUEST_CONF_BASE}/guests/${guestname} \ + --xen-disk=${devname} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error setting disk in xen configuration" + exit 1 + fi + + # Create partitions + partstart="0" + + # For each partition X the disk.cfg file should set a variable DISK_PARTX + # with a : separated list defining the partition: + # DISK_PART3="4:ext4:disk.tgz" means that partition 3 should be 4G formated + # with ext4 and initialized with the content of disk.tgz + for part in $(seq 1 4); do + eval partdesc="\${DISK_PART${part}:-0}" + size=$(echo ${partdesc} | sed -e "s/\(.*\):.*:.*/\1/") + fstype=$(echo ${partdesc} | sed -e "s/.*:\(.*\):.*/\1/") + content=$(echo ${partdesc} | sed -e "s/.*:.*:\(.*\)/\1/") + + if [ "${size}" -ne 0 ]; then + # Size is expressed in GB, pass it in MB + size=$(expr ${size} \* 1024) + partend=$(expr ${partstart} + ${size}) + + # Let first MB of disk free for partition table + if [ ${partstart} -eq 0 ]; then + partstart="1" + fi + + # Create partition + echo "parted -s ${devname} unit MB mkpart primary ${partstart}" \ + "${partend}" >> ${LOGFILE} 2>&1 + parted -s ${devname} unit MB mkpart primary ${partstart} \ + ${partend} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error adding partition ${part}" + exit 1 + fi + + # Set next partition start to current partition end + partstart="${partend}" + + # Sync to see the created partition + echo "sync" >> ${LOGFILE} 2>&1 + sync >> ${LOGFILE} 2>&1 + + # Prepare format command + if [ -n "${fstype}" ]; then + case ${fstype} in + vfat|ext2|ext3|ext4) + formatcmd="mkfs.${fstype} -F" + ;; + swap) + formatcmd="mkswap" + ;; + *) + echo "${PREF} partition ${part} of ${guestname}" \ + "fstype is invalid: ${fstype}" + exit 1 + ;; + esac + else + formatcmd="" + fi + + # Attach disk to xen + echo "xl block-attach 0 phy:${devname} xvda w" >> ${LOGFILE} 2>&1 + xl block-attach 0 phy:${devname} xvda w >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error attaching partition ${part}" + exit 1 + fi + + + # Loop for 20s to wait until /dev/xvdaX appears + i=0 + while [ ! -b /dev/xvda${part} ]; do + ((i++)) + if [[ "$i" == '40' ]]; then + break; + fi + sleep 0.5 + done + + if [ ! -b /dev/xvda${part} ]; then + echo "${PREF} Partition ${part} creation error" + xenguest_detach_disk + exit 1 + fi + + if [ -n "${formatcmd}" ]; then + echo "${formatcmd} /dev/xvda${part}" >> ${LOGFILE} 2>&1 + ${formatcmd} /dev/xvda${part} + if [ $? -ne 0 ]; then + echo "${PREF} Cannot create partition ${part} FS" + xenguest_detach_disk + exit 1 + fi + fi + + case ${content} in + *.img*) + decompress="" + case ${content} in + *.img.gz) + decompress='zcat' + ;; + *.img.bz2) + decompress='bzcat' + ;; + *.img) + decompress='cat' + ;; + *) + # invalid/unknown compression type + echo "${PREF} Invalid file format in disk ${content}" + xenguest_detach_disk + exit 1 + ;; + esac + # dd into partition + echo "xenguest-mkimage extract-disk-file ${guestfile} " \ + "${content} | ${decompress} | dd of=/dev/xvda${part} " >> ${LOGFILE} 2>&1 + xenguest-mkimage extract-disk-file ${guestfile} ${content} \ + | ${decompress} | dd of=/dev/xvda${part} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Cannot populate partition ${part}" + xenguest_detach_disk + exit 1 + fi + ;; + *.tar*) + tararg="" + case ${content} in + *.tar.gz) + tararg="z" + ;; + *.tar.bz2) + tararg="j" + ;; + *.tar.xz) + tararg="J" + ;; + *.tar) + tararg="" + ;; + *) + # invalid/unknown tar type + echo "${PREF} Invalid file format in disk ${content}" + xenguest_detach_disk + exit 1 + ;; + esac + + # must mount the partition and extract + mntdir=$(mktemp -d) + echo "mount /dev/xvda${part} ${mntdir}" >> ${LOGFILE} 2>&1 + mount /dev/xvda${part} ${mntdir} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Cannot mount partition ${part}" + xenguest_detach_disk + rm -rf ${mntdir} + exit 1 + fi + + # tar and unmount + echo "xenguest-mkimage extract-disk-file ${guestfile}" \ + "${content} | tar -C ${mntdir} -x${tararg}f - " \ + >> ${LOGFILE} 2>&1 + xenguest-mkimage extract-disk-file ${guestfile} ${content} \ + | tar -C ${mntdir} -x${tararg}f - >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Cannot populate partition ${part}" + umount ${mntdir} + rm -rf ${mntdir} + xenguest_detach_disk + exit 1 + fi + echo "umount ${mntdir}" >> ${LOGFILE} 2>&1 + umount ${mntdir} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error unmounting ${part}" + xenguest_detach_disk + rm -rf ${mntdir} + exit 1 + fi + rm -rf ${mntdir} + ;; + *) + #invalid content type + ;; + esac + + # Detach disk + xenguest_detach_disk + fi + done + +} + +function xenguest_guest_create() +{ + guestfile="$1" + guestname="$2" + + # extract xenguest tar + # put xen config in etc ? + # if disk config file: + # disk init + # add partititions + + echo "${PREF} Create ${guestname} using ${guestfile}" + rm -rf ${XENGUEST_CONF_BASE}/guests/${guestname} + mkdir -p ${XENGUEST_CONF_BASE}/guests/${guestname} + + echo "xenguest-mkimage extract-config ${guestfile}" \ + "${XENGUEST_CONF_BASE}/guests/${guestname}" >> ${LOGFILE} 2>&1 + xenguest-mkimage extract-config ${guestfile} \ + ${XENGUEST_CONF_BASE}/guests/${guestname} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error extracting guest image" + exit 1 + fi + + # Set guest name inside config + echo "xenguest-mkimage update ${XENGUEST_CONF_BASE}/guests/${guestname}" \ + "--xen-name=${guestname}" >> ${LOGFILE} 2>&1 + xenguest-mkimage update ${XENGUEST_CONF_BASE}/guests/${guestname} \ + --xen-name=${guestname} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error setting guest name" + exit 1 + fi + + xenguest_disk_init ${guestname} ${guestfile} +} + +function xenguest_guest_remove() +{ + guestname="$1" + devname="/dev/${XENGUEST_VOLUME_NAME}/${guestname}" + + # check if guest had a volume + echo "lvs ${XENGUEST_VOLUME_NAME}/${guestname}" >> ${LOGFILE} 2>&1 + lvs ${XENGUEST_VOLUME_NAME}/${guestname} >> ${LOGFILE} 2>&1 + if [ $? -eq 0 ]; then + # Remove guest volume + echo "lvremove -y ${devname}" >> ${LOGFILE} 2>&1 + lvremove -y ${devname} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error removing volume ${guestname}" + exit 1 + fi + fi + + # remove guest files + rm -rf ${XENGUEST_CONF_BASE}/guests/${guestname} +} + +function xenguest_guest_start() +{ + guestname="${1}" + guestdir=${XENGUEST_CONF_BASE}/guests/${guestname} + + # Get guest configuration + source ${guestdir}/params.cfg + + pushd ${guestdir} > /dev/null 2>&1 + + # create config by merging all configurations together + cat guest.cfg $(find guest.d -type f 2> /dev/null) > ${guestname}.cfg + + # Build init script lists (ignore non existing dirs errors, + # sort alphabetically and run global scripts first) + init_pre="$(find ${XENGUEST_CONF_BASE}/init.pre -type f 2> /dev/null | \ + sort) $(find ${guestdir}/init.pre -type f 2> /dev/null | sort)" + init_d="$(find ${XENGUEST_CONF_BASE}/init.d -type f 2> /dev/null | \ + sort) $(find ${guestdir}/init.d -type f 2> /dev/null | sort)" + init_post="$(find ${XENGUEST_CONF_BASE}/init.post -type f 2> /dev/null | \ + sort) $(find ${guestdir}/init.post -type f 2> /dev/null | sort)" + + # call pre init scripts + for f in ${init_pre}; do + echo "$f ${guestname}" >> ${LOGFILE} 2>&1 + $f ${guestname} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + rm -f ${guestname}.cfg + popd > /dev/null 2>&1 + echo "${PREF} Error during pre init script of ${guestname}" + exit 1 + fi + done + + # Create non started guest + echo "xl create -p ${guestname}.cfg" >> ${LOGFILE} 2>&1 + xl create -p ${guestname}.cfg >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + rm -f ${guestname}.cfg + popd > /dev/null 2>&1 + echo "${PREF} Error starting ${guestname}" + exit 1 + fi + + # call init scripts + for f in ${init_d}; do + echo "$f ${guestname}" >> ${LOGFILE} 2>&1 + $f ${guestname} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + rm -f ${guestname}.cfg + echo "xl destroy ${guestname}" >> ${LOGFILE} 2>&1 + xl destroy ${guestname} >> ${LOGFILE} 2>&1 + popd > /dev/null 2>&1 + echo "${PREF} Error during init script of ${guestname}" + exit 1 + fi + done + + # Start guest + echo "xl unpause ${guestname}" >> ${LOGFILE} 2>&1 + xl unpause ${guestname} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + rm -f ${guestname}.cfg + popd > /dev/null 2>&1 + echo "${PREF} Error starting ${guestname}" + exit 1 + fi + + # call post init scripts + for f in ${init_post}; do + echo "$f ${guestname}" >> ${LOGFILE} 2>&1 + $f ${guestname} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + rm -f ${guestname}.cfg + echo "xl destroy ${guestname}" >> ${LOGFILE} 2>&1 + xl destroy ${guestname} >> ${LOGFILE} 2>&1 + popd > /dev/null 2>&1 + echo "${PREF} Error during post init script of ${guestname}" + exit 1 + fi + done + + rm -f ${guestname}.cfg + popd > /dev/null 2>&1 +} + +function xenguest_guest_stop() +{ + guestname="${1}" + echo "xl shutdown ${guestname}" >> ${LOGFILE} 2>&1 + xl shutdown ${guestname} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error stopping ${guestname}" + exit 1 + fi +} + +function check_guest_arg() +{ + cmd="${1}" + guestname="${2:-}" + if [ -z "${guestname:-}" ]; then + echo "${PREF} Usage ${this} ${cmd} GUESTNAME" + exit 1 + fi +} + +function check_guest_exist() +{ + guestname="${1}" + if [ ! -f ${XENGUEST_CONF_BASE}/guests/${guestname}/guest.cfg -o \ + ! -f ${XENGUEST_CONF_BASE}/guests/${guestname}/params.cfg ]; then + echo "${PREF} Invalid guest name: ${guestname}" + exit 1 + fi +} + +function check_guest_running() +{ + guestname="${1}" + running=$(xl list | awk 'NR > 1 {print $1}' | grep "${guestname}" || echo) + if [ ! "${running}" = "${guestname}" ]; then + echo "${PREF} Guest ${guestname} is not running" + exit 1 + fi +} + +function check_guest_not_running() +{ + guestname="${1}" + running=$(xl list | awk 'NR > 1 {print $1}' | grep "${guestname}" || echo) + if [ "${running}" = "${guestname}" ]; then + echo "${PREF} Guest ${guestname} is running" + exit 1 + fi +} + +cmd="${1:-help}" +arg1="${2:-}" +arg2="${3:-}" + +case ${cmd} in + help|--help|-h|-?) + usage + exit 0 + ;; + create) + guestfile="${arg1}" + guestname="${arg2}" + if [ -z "${guestfile}" -o ! -f "${guestfile}" ]; then + echo "${PREF} Usage ${this} create XENGUEST_FILE [NAME]" + exit 1 + fi + if [ -z "${guestname}" ]; then + guestname=$(basename ${guestfile} .xenguest) + fi + + if [ -f ${XENGUEST_CONF_BASE}/guests/${guestname}/guest.cfg ]; then + # Guest already exist + echo "${PREF} A guest ${guestname} already exist" + exit 1 + fi + + xenguest_guest_create ${guestfile} ${guestname} + ;; + remove) + guestname="${arg1:-}" + check_guest_arg ${cmd} ${guestname} + check_guest_exist ${guestname} + # We need to stop the guest first + running=$(xl list | awk 'NR > 1 {print $1}' | grep "${guestname}" \ + || echo) + if [ "${running}" = "${guestname}" ]; then + echo "xl destroy ${guestname}" >> ${LOGFILE} 2>&1 + xl destroy ${guestname} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error killing ${guestname}" + exit 1 + fi + fi + xenguest_guest_remove ${guestname} + ;; + start) + guestname="${arg1:-}" + check_guest_arg ${cmd} ${guestname} + check_guest_exist ${guestname} + check_guest_not_running ${guestname} + xenguest_guest_start ${guestname} + ;; + stop|shutdown) + guestname="${arg1:-}" + check_guest_arg ${cmd} ${guestname} + check_guest_exist ${guestname} + check_guest_running ${guestname} + xenguest_guest_stop ${guestname} + ;; + kill|destroy) + guestname="${arg1:-}" + check_guest_arg ${cmd} ${guestname} + check_guest_exist ${guestname} + check_guest_running ${guestname} + echo "xl destroy ${guestname}" >> ${LOGFILE} 2>&1 + xl destroy ${guestname} >> ${LOGFILE} 2>&1 + if [ $? -ne 0 ]; then + echo "${PREF} Error killing ${guestname}" + exit 1 + fi + ;; + list) + if [ -d ${XENGUEST_CONF_BASE}/guests ]; then + for f in $(find ${XENGUEST_CONF_BASE}/guests -mindepth 1 \ + -maxdepth 1 -type d -exec basename {} \;); do + if [ -f ${XENGUEST_CONF_BASE}/guests/$f/guest.cfg ]; then + echo "$f" + fi + done + fi + ;; + status) + guestname="${arg1}" + if [ -n "${guestname}" ]; then + check_guest_exist ${guestname} + if xl list | awk 'NR > 1 {print $1}' | grep "${guestname}" > \ + /dev/null 2>&1; then + echo "${guestname}: Running" + else + echo "${guestname}: Stopped" + fi + else + guestlist=$($this list) + if [ -n "${guestlist}" ]; then + for f in ${guestlist}; do + $this status $f + done + fi + fi + ;; + *) + echo "${PREF} Invalid argument ${cmd}" + exit 1 + ;; +esac + diff --git a/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-mkimage b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-mkimage new file mode 100755 index 00000000..4c1b4a87 --- /dev/null +++ b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-mkimage @@ -0,0 +1,772 @@ +#!/bin/bash +# This script must be used to manipulate xenguest images +# +# xenguest image topology: +# params.cfg: guest global configuration file. Only edited using this script. +# guest.cfg: xen main configuration file. Only edited using this script. +# guest.d: directory contains files with custom xen configuration entries +# which are appended to guest.cfg before starting the guest +# files: directory where files used by xen configuration are stored +# disk.cfg: guest disk configuration file. Only edited using this script. +# (dtb, kernel image, etc) +# disk: directory where files for disk creation are stored +# init.[pre,d,post]: directories containing init pre, base and post scripts +set -u +set -e + +this="$0" + +IMAGE_TMPDIR="" + +usage() { + cat <<EOF +Usage $this ACTION XENGUEST [ARGS] + +Where XENGUEST is a xenguest image file or a xenguest directory. + +The following actions are supported: +help Display this help +create Create a xenguest image +update Update/modify a xenguest image +partial Create partial xenguest image in a directory +pack Pack a xenguest directory into an image +check Check a xenguest image +dump-paramsconfig Display the guest configuration of a xenguest image +dump-xenconfig Display the xen configuration of a xenguest image +dump-diskconfig Display the disk configuration of a xenguest image +dump-init Display init scripts of a xenguest image +extract Extract a xenguest image content +extract-config Extract the guest configuration from a xenguest image +extract-disk-file Extract a disk file from a xenguest image +Use $this ACTION --help to have help on a specific action and its arguments. +EOF +} + +usage-check() { + cat <<EOF +Usage $this check XENGUEST + +Check a xenguest image or a xenguest directory. +EOF +} + +usage-update-create() { + cat <<EOF +All arguments are handled in order. + +Global configuration for the guest +--guest-config-reset reset guest global configuration +--set-param=PARAM disable parameter PARAM in guest global configuration +--set-param=PARAM=VAL set parameter PARAM to value VAL in guest global + configuration. + Example of parameters supported are: + GUEST_AUTOBOOT: if set to 1 (default), guest will be + automatically created and started during host init. + +Xen configuration for the guest +--xen-reset-config reset xen guest configuration to default +--xen-name= disable name parameter in xen configuration +--xen-name=NAME set guest name in xen configuration +--xen-kernel= disable guest kernel parameter in xen configuration +--xen-kernel=FILE set guest kernel to FILE (file is added and xen + configuration is set to use it) +--xen-memory set guest memory size (in MB) +--xen-vcpus set guest number of virtual cpus +--xen-clean-extra set guest command line (extra) to an empty string +--xen-extra=ARG append ARG to the guest command line (with space) + use this several time to set command line. + To set the command line to "console=ttyS0 rw" do + --xen-extra=console=ttyS0 --xen-extra=rw +--xen-root= disable root parameter in xen configuration +--xen-root=ROOT set guest root in xen configuration +--xen-device-tree= disable device tree parameter in xen configuration +--xen-device-tree=FILE set guest device tree in xen configuration and add + file to xen files +--xen-disk= disable disk parameter in xen configuration +--xen-disk=DEV set guest disk to device DEV (phy:DEV,xvda,w is set) +--xen-append=FILE append FILE content to xen configuration + +Xen files +--xen-add-file=SRC:DST add file SRC as file DST in the xenguest image. + If DST already exist in the image, it is overwritten. + DST must be the same as arguments passed to other + options (like --xen-kernel) +--xen-rm-file=DST remove file DST from the xenguest image. + +Init configuration + This can be used to add init scripts for the guest. There are 3 possible init + scripts which are called at different time. The pre scripts are called first, + then the xen guest is created in pause and standard init scripts are called. + Finally the xen guest is started then the post init scripts are called. + Each script is called with the name of the guest as first argument and + multiple scripts can be added (they must have different names). + +--init-script=FILE add FILE as init script +--init-pre=FILE add FILE as pre init script +--init-post=FILE add FILE as post init script + +Disk configuration +--disk-reset-config reset disk guest configuration to default (no disk) +--disk-size=SZ set guest disk size (in GB) +--disk-device=DEV set device to be used to create the guest disk + if unset or set to an empty string, the volume will be + create in the default manager volume group. +--disk-add-part=DEF add a partition to the guest disk with definition DEF + a partition definition must have the following format: + ID:SIZE:FORMAT:CONTENT where: + - ID is the partition numeric ID (1 to 4) + - FORMAT is the filesystem format (supported formats + are none, vfat, swap, ext2, ext3 and ext4) or can be + left empty to not format + - CONTENT can be used to point to a file added using + --disk-add-file to be used as partition initial + content (tar file or img file) +--disk-rm-part=ID remove partition ID from the guest disk +--disk-add-file=SRC:DST add file SRC as disk file DST in the xenguest image. + DST can then be used as a partition CONTENT. +--disk--rm-file=DST remove disk file DST from the xenguest image. +EOF +} + +usage-create() { + cat <<EOF +Usage $this create XENGUEST [ARGS] + +Create a xenguest image as XENGUEST file. + +EOF + usage-update-create +} + +usage-update() { + cat <<EOF +Usage $this update XENGUEST [ARGS] + +Update or modify a xenguest image or a xenguest directory. + +EOF + usage-update-create +} + +usage-pack() { + cat <<EOF +Usage $this pack XENGUEST DESTFILE + +Pack a xenguest directory in XENGUEST to create a xenguest image DESTFILE. + +EOF +} + +usage-partial() { + cat <<EOF +Usage $this partial XENGUEST [ARGS] + +Update or modify a partial xenguest image. + +EOF + usage-update-create +} + +usage-dump-paramsconfig() { + cat <<EOF +Usage $this dump-paramsconfig XENGUEST + +Dump the guest parameters of a xenguest image or directory +EOF +} + +usage-dump-xenconfig() { + cat <<EOF +Usage $this dump-xenconfig XENGUEST + +Dump the xen configuration of a xenguest image or directory +EOF +} + +usage-dump-diskconfig() { + cat <<EOF +Usage $this dump-diskconfig XENGUEST + +Dump the disk configuration of a xenguest image or directory +EOF +} + +usage-extract() { + cat <<EOF +Usage $this extract XENGUEST DESTDIR + +Extract guest to DESTDIR +EOF +} + +usage-extract-config() { + cat <<EOF +Usage $this extract-config XENGUEST DESTDIR + +Extract guest configuration to DESTDIR +EOF +} + +usage-extract-disk-file() { + cat <<EOF +Usage $this extract-disk-file XENGUEST DISKFILE + +Extract disk file DISKFILE to stdout. +EOF +} + +check_image() { + local tstfile=${1} + + if [ ! -e ${tstfile} -o ! -w ${tstfile} ]; then + echo "Error: File ${tstfile} does not exist or is not writeable" + exit 1 + fi + + if [ -f ${tstfile} ]; then + # This is a xenguest file + local res=$(tar -tvf ${tstfile} ./guest.cfg ./disk.cfg \ + ./params.cfg > /dev/null 2>&1 || echo "error") + if [ -n "${res}" ]; then + echo "Error: File ${tstfile} is not a valid xenguest" + exit 1 + fi + elif [ -d ${tstfile} ]; then + if [ ! -f ${tstfile}/guest.cfg -o ! -f ${tstfile}/disk.cfg -o \ + ! ${tstfile}/params.cfg ]; then + echo "Error: Directory ${tstfile} is not a valid xenguest" + exit 1 + fi + fi +} + +params_config_reset() { + cat <<EOF > ${IMAGE_TMPDIR}/params.cfg +# Xenguest-image guest global configuration +# +# !! This file must not be modified manually !! +# +# You can use xenguest-image to modify parameters. +# + +# Guest auto boot during Dom0 init +GUEST_AUTOBOOT="1" +EOF +} + +params_config_setparam() { + param="${1}" + shift + value="$@" + + if [ -z "$value" ]; then + sed -i "/.*${param}=.*/d" ${IMAGE_TMPDIR}/params.cfg + elif grep -e "^${param}=" ${IMAGE_TMPDIR}/params.cfg > /dev/null; then + sed -i "s/${param}=\".*\"/${param}=\"${value}\"/" \ + ${IMAGE_TMPDIR}/params.cfg + else + echo "${param}=\"${value}\"" >> ${IMAGE_TMPDIR}/params.cfg + fi +} + +xen_config_reset() { + cat <<EOF > ${IMAGE_TMPDIR}/guest.cfg +# Xenguest-image main configuraiton +# +# !! This file must not be modified manually !! +# +# You can use xenguest-image to modify parameters. +# +# You can add custom entries to configuration in the guest.d directory. + +# Guest name (set by manager when guest is created) +# name = "" + +# Guest memory size in MB +memory = 1024 + +# Number of VCPUS +vcpus = 1 + +# Guest command line +extra = "earlyprintk=xenboot console=hvc0 rw" + +# Guest root filesystem device (from guest point of view) +# root = "/dev/xvda2" + +# Disk that will be used by the guest (set by manager when guest is created) +# disk = ['phy:/dev/vg-xen/guestname,xvda,w'] + +EOF +} + +get_param_file() { + param="${1}" + + if grep ${param} ${IMAGE_TMPDIR}/guest.cfg > /dev/null 2>&1; then + echo "${IMAGE_TMPDIR}/guest.cfg" + else + if [ ! -f ${IMAGE_TMPDIR}/guest.d/${param}.cfg ]; then + mkdir -p ${IMAGE_TMPDIR}/guest.d + echo "# ${param} = \"\"" > ${IMAGE_TMPDIR}/guest.d/${param}.cfg + fi + echo "${IMAGE_TMPDIR}/guest.d/${param}.cfg" + fi +} + +xen_config_disable_param() { + param="${1}" + dst=$(get_param_file ${param}) + + sed -i "s@.*\(${param} = .*\)\$@# \1@" ${dst} +} + +xen_config_set_number() { + param="${1}" + shift + value="$@" + dst=$(get_param_file ${param}) + + sed -i "s@.*${param} = .*@${param} = ${value}@" ${dst} +} + +xen_config_set_string() { + param="${1}" + shift + value="$@" + dst=$(get_param_file ${param}) + + sed -i "s@.*${param} = .*@${param} = \"${value}\"@" ${dst} +} + +xen_config_append_string() { + param="${1}" + shift + value="$@" + dst=$(get_param_file ${param}) + + sed -i "s@.*${param} = \"\([^\"]*\)\"@${param} = \"\1 ${value}\"@" ${dst} +} + +xen_config_set_list() { + param="${1}" + shift + value=$(echo $@ | tr " " ",") + dst=$(get_param_file ${param}) + + sed -i "s@.*${param} = .*@${param} = ['${value}']@" ${dst} +} + +disk_config_reset() { + echo "DISK_SIZE=\"0\"" > ${IMAGE_TMPDIR}/disk.cfg + echo "DISK_DEVICE=\"\"" >> ${IMAGE_TMPDIR}/disk.cfg +} + +disk_config_rm_part() { + partid=$1 + sed -i "/DISK_PART${partid}=.*/d" ${IMAGE_TMPDIR}/disk.cfg +} + +disk_config_add_part() { + partconf="${1}" + partid=$(echo ${partconf} | sed -e "s/:.*//") + partinfo=$(echo ${partconf} | sed -e "s/[^:]*://") + + # Make sure we don't add the same partition twice + disk_config_rm_part ${partid} + echo "DISK_PART${partid}=\"${partinfo}\"" >> \ + ${IMAGE_TMPDIR}/disk.cfg +} + +# We need an action as first argument +action="${1:-}" + +if [ -z "${action}" ]; then + echo "Error: No ACTION provided" + usage + exit 1 +fi + +# Only help does not require a xenguest argument so treat this first +# while there we also check that user is asking for a supported action +case $action in + help|--help|-h|-?) + usage + exit 0 + ;; + check|create|update|pack|partial) + ;; + dump-xenconfig|dump-diskconfig|dump-init|dump-paramsconfig) + ;; + extract|extract-config|extract-disk-file) + ;; + *) + echo "Error: Invalid action $action" + exit 1 + ;; +esac + +# Second argument should be the file name or directory +guestfile="${2:-}" + +# Handle user asking for help on a specific action +case $guestfile in + help|--help|-h|-?) + usage-${action} + exit 0 + ;; +esac + +if [ -z "${guestfile}" ]; then + echo "Error: no GUESTFILE provided" + usage + exit 1 +fi + +shift 2 + +case ${action} in + check) + check_image ${guestfile} + echo "Image is OK" + exit 0 + ;; + dump-paramsconfig) + check_image ${guestfile} + echo "Guest configuration:" + if [ -f ${guestfile} ]; then + tar -xOf ${guestfile} ./params.cfg + else + cat ${guestfile}/params.cfg + fi + exit 0 + ;; + dump-xenconfig) + check_image ${guestfile} + echo "Xen configuration:" + if [ -f ${guestfile} ]; then + tar -xOf ${guestfile} ./guest.cfg + tar -xOf ${guestfile} ./guest.d 2> /dev/null || true + else + cat ${guestfile}/guest.cfg + cat ${guestfile}/guest.d/* 2> /dev/null || true + fi + echo + exit 0 + ;; + dump-diskconfig) + check_image ${guestfile} + echo "Disk configuration:" + if [ -f ${guestfile} ]; then + tar -xOf ${guestfile} ./disk.cfg + else + cat ${guestfile}/disk.cfg + fi + echo + exit 0 + ;; + dump-init) + check_image ${guestfile} + for init in init.d init-pre init-post; do + echo "=== ${init} ===" + if [ -f ${guestfile} ]; then + tar -xOf ${guestfile} ./${init} 2> /dev/null || \ + echo "No ${init} scripts." + else + cat ${guestfile}/${init}/* 2> /dev/null || \ + echo "No ${init} scripts." + fi + echo "===============" + echo + done + exit 0 + ;; + pack) + check_image ${guestfile} + if [ ! -d ${guestfile} ]; then + echo "Error: Pack can only be done on a xenguest directory" + exit 1 + fi + + if [ -z "${1:-}" ] || [ -f ${1} ]; then + echo "Error: No destination file or already existing file" + exit 1 + fi + + tar -C ${guestfile} -cf ${1} . + exit 0 + ;; + extract) + check_image ${guestfile} + if [ -d ${guestfile} ]; then + echo "Error: Cannot extract config from xenguest directory" + exit 1 + fi + + if [ -z "${1:-}" ] || [ ! -d ${1} ]; then + echo "Error: No destination directory for image extract" + exit 1 + fi + + tar -C ${1} -xf ${guestfile} + exit 0 + ;; + extract-config) + check_image ${guestfile} + if [ -d ${guestfile} ]; then + echo "Error: Cannot extract config from xenguest directory" + exit 1 + fi + + if [ -z "${1:-}" ] || [ ! -d ${1} ]; then + echo "Error: No destination directory for config extract" + exit 1 + fi + + #extract all but disk files + tar -C ${1} --exclude='./disk' -xf ${guestfile} + exit 0 + ;; + extract-disk-file) + check_image ${guestfile} + + if [ -d ${guestfile} ]; then + echo "Error: Cannot extract disk file from xenguest directory" >&2 + exit 1 + fi + + if [ -z "${1:-}" ]; then + echo "Error: No file to extract" >&2 + exit 1 + fi + + tar -xOf ${guestfile} ./disk/${1} + exit 0 + ;; + create) + if [ -f ${guestfile} ]; then + echo "Error: File ${guestfile} already exist" + exit 1 + elif [ -d ${guestfile} ]; then + if [ -n "$(ls -A ${guestfile})" ]; then + echo "Error: Directory ${guestfile} is not empty" + exit 1 + fi + IMAGE_TMPDIR=$(realpath -m ${guestfile}) + else + IMAGE_TMPDIR=$(mktemp -d) + fi + + # Create initial content + params_config_reset + xen_config_reset + disk_config_reset + ;; + update) + check_image ${guestfile} + + if [ -f ${guestfile} ]; then + # Extract the image to update it + IMAGE_TMPDIR=$(mktemp -d) + tar -C ${IMAGE_TMPDIR} -xf ${guestfile} + else + IMAGE_TMPDIR=$(realpath -m ${guestfile}) + fi + ;; + partial) + if [ -e ${guestfile} -a ! -d ${guestfile} ]; then + echo "Error: Invalid partial output directory" + exit 1 + fi + mkdir -p ${guestfile} + IMAGE_TMPDIR=$(realpath -m ${guestfile}) + ;; + *) + echo "Invalid action ${action}" + usage + exit 1 + ;; +esac + +# Process command line arguments +for arg in "${@}"; do + case ${arg} in + --*=*) + optarg=$(echo ${arg} | sed -e "s/[^=]*=//") + ;; + *) + optarg="" + ;; + esac + + case ${arg} in + --guest-reset-config) + params_config_reset + ;; + --set-param=*=*) + param_name=$(echo $optarg | sed -e "s/=.*//") + param_value=$(echo $optarg | sed -e "s/[^=]*=//") + params_config_setparam "$param_name" "$param_value" + ;; + --set-param=*) + params_config_setparam "$optarg" + ;; + --xen-reset-config) + xen_config_create + ;; + --xen-name=*) + if [ -z "${optarg}" ]; then + xen_config_disable_param "name" + else + xen_config_set_string "name" "${optarg}" + fi + ;; + --xen-kernel=*) + if [ -z "${optarg}" ]; then + xen_config_disable_param "kernel" + rm -f ${IMAGE_TMPDIR}/files/kernel + else + if [ ! -f ${optarg} ]; then + echo "Error: invalid kernel file ${optarg}" + exit 1 + fi + xen_config_set_string "kernel" "files/kernel" + mkdir -p ${IMAGE_TMPDIR}/files + install -m 644 ${optarg} ${IMAGE_TMPDIR}/files/kernel + fi + ;; + --xen-memory=*) + xen_config_set_number "memory" ${optarg} + ;; + --xen-vcpus=*) + xen_config_set_number "vcpus" ${optarg} + ;; + --xen-clean-extra) + xen_config_set_string "extra" "" + ;; + --xen-extra=*) + xen_config_append_string "extra" ${optarg} + ;; + --xen-root=*) + if [ -z "${optarg}" ]; then + xen_config_disable_param "root" + else + xen_config_set_string "root" "${optarg}" + fi + ;; + --xen-device-tree=*) + if [ -z "${optarg}" ]; then + xen_config_disable_param "device_tree" + rm -f ${IMAGE_TMPDIR}/files/guest.dtb + else + if [ ! -f ${optarg} ]; then + echo "Error: invalid dtb file ${optarg}" + exit 1 + fi + xen_config_set_string "device_tree" "files/guest.dtb" + mkdir -p ${IMAGE_TMPDIR}/files + install -m 644 ${optarg} ${IMAGE_TMPDIR}/files/guest.dtb + fi + ;; + --xen-disk=*) + if [ -z "${optarg}" ]; then + xen_config_disable_param "disk" + else + xen_config_set_list "disk" "phy:${optarg}" "xvda" "w" + fi + ;; + --xen-append=*) + if [ ! -f ${optarg} ]; then + echo "Error: invalid xen append file ${optarg}" + exit 1 + fi + mkdir -p ${IMAGE_TMPDIR}/guest.d + install -m 755 ${optarg} ${IMAGE_TMPDIR}/guest.d/. + ;; + --xen-add-file=*) + src=$(echo "${optarg}" | sed -e "s/:.*//") + dst=$(echo "${optarg}" | sed -e "s/.*://") + if [ ! -f ${src} ]; then + echo "Error: Invalid file: ${src}" + rm -rf ${IMAGE_TMPDIR} + exit 1 + fi + if [ -z "${dst}" ]; then + dst=$(basename ${src}) + fi + mkdir -p ${IMAGE_TMPDIR}/files/$(dirname ${dst}) + cp -f ${src} ${IMAGE_TMPDIR}/files/${dst} + ;; + --xen-rm-file=*) + rm -f ${IMAGE_TMPDIR}/files/${optarg} + ;; + --init-script=*|--init-pre=*|--init-post=*) + dst="" + case $arg in + --init-script=*) + dst="init.d" + ;; + --init-pre=*) + dst="init.pre" + ;; + --init-post=*) + dst="init.post" + ;; + esac + if [ ! -f ${optarg} ]; then + echo "${optarg} does not point to a valid file" + exit 1 + else + mkdir -p ${IMAGE_TMPDIR}/${dst} + install -m 755 ${optarg} ${IMAGE_TMPDIR}/${dst}/. + fi + ;; + --disk-reset-config) + disk_config_reset + ;; + --disk-size=*) + sed -i "s/DISK_SIZE=.*/DISK_SIZE=\"${optarg}\"/" \ + ${IMAGE_TMPDIR}/disk.cfg + ;; + --disk-device=*) + sed -i "s/DISK_DEVICE=.*/DISK_SIZE=\"${optarg}\"/" \ + ${IMAGE_TMPDIR}/disk.cfg + ;; + --disk-add-part=*) + disk_config_add_part ${optarg} + ;; + --disk-rm-part=*) + disk_config_rm_part ${optarg} + ;; + --disk-add-file=*) + src=$(echo "${optarg}" | sed -e "s/:.*//") + dst=$(echo "${optarg}" | sed -e "s/.*://") + if [ ! -f ${src} ]; then + echo "Error: Invalid disk file: ${src}" + rm -rf ${IMAGE_TMPDIR} + exit 1 + fi + if [ -z "${dst}" ]; then + dst=$(basename ${src}) + fi + mkdir -p ${IMAGE_TMPDIR}/disk/$(dirname ${dst}) + cp -f ${src} ${IMAGE_TMPDIR}/disk/${dst} + ;; + --disk-rm-file=*) + rm -f ${IMAGE_TMPDIR}/disk/${optarg} + ;; + *) + echo "Unsupported command: ${arg}" + exit 1 + ;; + esac +done + +if [ ! -d ${guestfile} ]; then + # If the original guest was in a file we need to repack the file + # with the changes we did on it in the IMAGE_TMPDIR + rm -f ${guestfile} + tar -C ${IMAGE_TMPDIR} -cf ${guestfile} . + rm -rf ${IMAGE_TMPDIR} +fi + diff --git a/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-network-bridge-dhcp.cfg.in b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-network-bridge-dhcp.cfg.in new file mode 100644 index 00000000..6e063793 --- /dev/null +++ b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-network-bridge-dhcp.cfg.in @@ -0,0 +1,3 @@ +# Xenguest Network Bridge interface configuration +auto ###BRIDGE_NAME### +iface ###BRIDGE_NAME### inet dhcp diff --git a/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-network-bridge.in b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-network-bridge.in new file mode 100755 index 00000000..2278b80c --- /dev/null +++ b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-network-bridge.in @@ -0,0 +1,44 @@ +#!/bin/sh +# +# Xenguest Network Bridge init +# This script creates a network bridge and add host interfaces to it +# It will then be used by xen guests to connect to the external nework +# + +INTFS="###BRIDGE_MEMBERS###" +BR_INTF="###BRIDGE_NAME###" + +case "$1" in + start) + echo "Starting $BR_INTF" + brctl addbr $BR_INTF + for intf in $INTFS; do + echo "Adding $intf to $BR_INTF" + brctl addif $BR_INTF $intf + done + ;; + status) + true + ;; + stop) + echo "Stopping $BR_INTF" + ifdown $BR_INTF + brctl delbr $BR_INTF + ;; + reload) + echo >&2 'Reload not available; use force-reload'; exit 1 + ;; + force-reload|restart) + echo "Restarting host-bridge" + $0 stop + $0 start + ;; + *) + # do not advertise unreasonable commands that there is no reason + # to use with this device + echo $"Usage: $0 {start|stop|status|restart|force-reload}" + exit 1 +esac + +exit $? + diff --git a/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/xenguest-base-image.bb b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/xenguest-base-image.bb new file mode 100644 index 00000000..fb665666 --- /dev/null +++ b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/xenguest-base-image.bb @@ -0,0 +1,119 @@ +# Create a xenguest base image +# +# This recipe creates a base image that is then extended by other recipes +# through xenguest-image class. +# xenguest image type is using this as base to add a kernel and a disk image +# to create a guest +# +# The recipe is also adding files in those directories to the xenguest image: +# - ${WORKDIR}/extend/disk-files: all files in this directory will be added to +# the guest disk files (using --disk-add-file) +# - ${WORKDIR}/extend/files: all files in this directory will be added to the +# guest xen files (using --xen-add-file) +# - ${WORKDIR}/extend/guest.d: all files in this directory will be added to +# the xen append configuration files (using --xen-append) +# - ${WORKDIR}/extend/init.[pre|post|d]: all files in those directories will +# be added to the corresponding init scripts (using --init-[pre|post|script]) +# You can bbappend this recipe and put files in ${WORKDIR}/extend to add +# elements to the image. +# + +DESCRIPTION = "Xenguest Base Image" +LICENSE = "MIT" + +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +# +# The following variables can contain SRC_URI compatible entries to add +# files to the xenguest image. +# You can set those variable in local.conf to add one or several files +# For example to add a boot.tar.gz file that has to be downloaded to the file +# useable for disk partition initialisation: +# XENGUEST_IMAGE_SRC_URI_DISK_FILES += "https://www.test.com/files/boot.tar.gz" + +# Add disk files +XENGUEST_IMAGE_SRC_URI_DISK_FILES ??= "" + +# Add xen files +XENGUEST_IMAGE_SRC_URI_XEN_FILES ??= "" + +# Add xen configuration elements +XENGUEST_IMAGE_SRC_URI_XEN_CONFIG ??= "" + +# Add pre init script +XENGUEST_IMAGE_SRC_URI_INIT_PRE ??= "" + +# Add init script +XENGUEST_IMAGE_SRC_URI_INIT ??= "" + +# Add post init script +XENGUEST_IMAGE_SRC_URI_INIT_POST ??= "" + +S = "${WORKDIR}" + +inherit deploy xenguest-image + +# parse XENGUEST_IMAGE_SRC_URI_ variables and add them to SRC_URI +python __anonymous() { + def parse_extend_variable(d, varname, destdir): + list = d.getVar(varname) + if list: + for entry in list.split(): + #Check the URL + try: + decode = bb.fetch.decodeurl(entry) + d.appendVar('SRC_URI', ' ' + entry + ';unpack=0;subdir=extend/' + destdir) + except: + bb.fatal("%s: %s contains an invalid URL: %s" \ + % (d.getVar('PF'), varname, entry)) + + parse_extend_variable(d, 'XENGUEST_IMAGE_SRC_URI_DISK_FILES', 'disk-files') + parse_extend_variable(d, 'XENGUEST_IMAGE_SRC_URI_XEN_FILES', 'files') + parse_extend_variable(d, 'XENGUEST_IMAGE_SRC_URI_XEN_CONFIG', 'guest.d') + parse_extend_variable(d, 'XENGUEST_IMAGE_SRC_URI_INIT_PRE', 'init.pre') + parse_extend_variable(d, 'XENGUEST_IMAGE_SRC_URI_INIT', 'init.d') + parse_extend_variable(d, 'XENGUEST_IMAGE_SRC_URI_INIT_POST', 'init.post') +} + +# Make sure we are removing old files before redoing a fetch +do_fetch[cleandirs] += "${WORKDIR}/extend" + +do_configure[noexec] = "1" +do_compile[noexec] = "1" +do_install[noexec] = "1" + +add_extend_files() { + local subdir="$1" + local cmd="$2" + local stripdest="${3:-n}" + + if [ -d ${WORKDIR}/extend/$subdir ]; then + filelist=$(find ${WORKDIR}/extend/$subdir -type f) + + if [ -n "$filelist" ]; then + for f in $filelist; do + if [ "$stripdest" = "y" ]; then + call_xenguest_mkimage update --$cmd=$f:$(basename $f) + else + call_xenguest_mkimage update --$cmd=$f + fi + done + fi + fi +} + +do_deploy() { + # Create a new image + xenguest_image_create + + # Add our extra files if any + add_extend_files "disk-files" "disk-add-file" "y" + add_extend_files "files" "xen-add-file" "y" + add_extend_files "guest.d" "xen-append" + add_extend_files "init.pre" "init-pre" + add_extend_files "init.d" "init-script" + add_extend_files "init.post" "init-post" +} + +addtask deploy after do_install before do_build + diff --git a/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/xenguest-manager.bb b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/xenguest-manager.bb new file mode 100644 index 00000000..65925d2a --- /dev/null +++ b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/xenguest-manager.bb @@ -0,0 +1,52 @@ +# Xenguest manager recipe +# +# xenguest-manager is a tool to control xen guest (e.g. create, start, stop) +# + +DESCRIPTION = "Xen Guest Manager" +LICENSE = "MIT" + +SRC_URI = " \ + file://xenguest-manager \ + file://xenguest-init \ + " +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +S = "${WORKDIR}" + +# Please refer to documentation/xenguest-manager.md for documentation on those +# parameters +XENGUEST_MANAGER_VOLUME_DEVICE ?= "/dev/sda2" +XENGUEST_MANAGER_VOLUME_NAME ?= "vg-xen" +XENGUEST_MANAGER_GUEST_DIR ?= "${datadir}/guests/" + +# We add an init script to create and start guests automatically +INITSCRIPT_NAME = "xenguest" +INITSCRIPT_PARAMS = "defaults 90" + +inherit update-rc.d + +do_compile() { + echo "XENGUEST_VOLUME_DEVICE=\"${XENGUEST_MANAGER_VOLUME_DEVICE}\"" > \ + xenguest-manager.conf + echo "XENGUEST_VOLUME_NAME=\"${XENGUEST_MANAGER_VOLUME_NAME}\"" >> \ + xenguest-manager.conf + echo "XENGUEST_GUEST_DIR=\"${XENGUEST_MANAGER_GUEST_DIR}\"" >> \ + xenguest-manager.conf +} + +do_install() { + install -d -m 755 ${D}${bindir} + install -m 755 xenguest-manager ${D}${bindir}/. + install -d -m 755 ${D}${sysconfdir}/xenguest + install -m 644 xenguest-manager.conf ${D}${sysconfdir}/xenguest/. + install -d -m 755 ${D}${sysconfdir}/init.d + install -m 755 xenguest-init ${D}${sysconfdir}/init.d/${INITSCRIPT_NAME} + install -d -m 755 ${D}${XENGUEST_GUEST_DIR} +} + +# Things that we need on the target +RDEPENDS_${PN} += "bash tar xenguest-mkimage lvm2 xen-tools parted e2fsprogs" + +FILES_${PN} += "${bindir}/xenguest-manager \ + ${sysconfdir}/xenguest" diff --git a/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/xenguest-mkimage.bb b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/xenguest-mkimage.bb new file mode 100644 index 00000000..6ea5fb10 --- /dev/null +++ b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/xenguest-mkimage.bb @@ -0,0 +1,31 @@ +# Xenguest mkimage recipe +# +# xenguest-mkimage is a tool to create/modify images to be used as xen guests +# Produced images contains a xen configuration and several optional components +# (kernel, device-tree, disk definition and files, init scripts) which all +# together fully define a full xen guest + +DESCRIPTION = "Xenguest mkimage tool" +LICENSE = "MIT" + +SRC_URI = "file://xenguest-mkimage" + +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +S = "${WORKDIR}" + +# Can be built native also to produce xenguest images during Yocto build +BBCLASSEXTEND = "native" + +do_configure[noexec] = "1" +do_compile[noexec] = "1" + +do_install() { + install -d -m 755 ${D}${bindir} + install -m 755 xenguest-mkimage ${D}${bindir}/. +} + +# We need bash and tar +RDEPENDS_${PN} = "bash tar" +FILES_${PN} = "${bindir}/xenguest-mkimage" + diff --git a/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/xenguest-network-bridge.bb b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/xenguest-network-bridge.bb new file mode 100644 index 00000000..babd694d --- /dev/null +++ b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/xenguest-network-bridge.bb @@ -0,0 +1,52 @@ +# Recipe to handle xenguest network configuration +DESCRIPTION = "XenGuest Network Bridge" + +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +S = "${WORKDIR}" + +# Please refer to documentation/xenguest-network-bridge.md for documentation on +# those parameters +XENGUEST_NETWORK_BRIDGE_NAME ?= "xenbr0" +XENGUEST_NETWORK_BRIDGE_MEMBERS ?= "eth0" +XENGUEST_NETWORK_BRIDGE_CONFIG ?= "xenguest-network-bridge-dhcp.cfg.in" + +SRC_URI = " \ + file://xenguest-network-bridge.in \ + file://xenguest-network-bridge-dhcp.cfg.in \ + file://network-bridge.sh.in \ + " + +# Bridge configurator needs to run before S01networking init script +# Prefix with a_ to make sure it is executed in runlevel 01 before others +INITSCRIPT_NAME = "a_xenguest-network-bridge" +INITSCRIPT_PARAMS = "defaults 01" + +inherit update-rc.d + +do_install() { + cat ${WORKDIR}/xenguest-network-bridge.in \ + | sed -e "s,###BRIDGE_MEMBERS###,${XENGUEST_NETWORK_BRIDGE_MEMBERS}," \ + | sed -e "s,###BRIDGE_NAME###,${XENGUEST_NETWORK_BRIDGE_NAME}," \ + > ${WORKDIR}/xenguest-network-bridge + cat ${WORKDIR}/${XENGUEST_NETWORK_BRIDGE_CONFIG} \ + | sed -e "s,###BRIDGE_NAME###,${XENGUEST_NETWORK_BRIDGE_NAME}," \ + > ${WORKDIR}/xenguest-network-bridge.cfg + cat ${WORKDIR}/network-bridge.sh.in \ + | sed -e "s,###BRIDGE_NAME###,${XENGUEST_NETWORK_BRIDGE_NAME}," \ + > ${WORKDIR}/network-bridge.sh + install -d -m 755 ${D}${sysconfdir}/init.d + install -m 755 ${WORKDIR}/xenguest-network-bridge \ + ${D}${sysconfdir}/init.d/${INITSCRIPT_NAME} + install -d -m 755 ${D}${sysconfdir}/network/interfaces.d + install -m 755 ${WORKDIR}/xenguest-network-bridge.cfg \ + ${D}${sysconfdir}/network/interfaces.d/. + install -d -m 755 ${D}${sysconfdir}/xenguest/init.pre + install -m 755 ${WORKDIR}/network-bridge.sh \ + ${D}${sysconfdir}/xenguest/init.pre/. +} + +RDEPENDS_${PN} += "bridge-utils" +FILES_${PN} += "${sysconfdir}/network/interfaces.d/xenguest-network-bridge.cfg" +FILES_${PN} += "${sysconfdir}/xenguest/init.pre/network-bridge.sh" diff --git a/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/xenguest-nodisk-image.bb b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/xenguest-nodisk-image.bb new file mode 100644 index 00000000..b2dbbe99 --- /dev/null +++ b/bsp/meta-arm/meta-arm-autonomy/recipes-extended/xenguest/xenguest-nodisk-image.bb @@ -0,0 +1,38 @@ +# Create a xenguest image with kernel but no rootfs or an external rootfs +DESCRIPTION = "Xenguest No Disk Image" +LICENSE = "MIT" + +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +S = "${WORKDIR}" + +inherit deploy xenguest-image + +# Name of the file we create in deploy +XENGUEST_IMAGE_NODISK_DEPLOY = "xenguest-nodisk-image.xenguest" + +# use a local copy to pack all together +XENGUEST_IMAGE_DEPLOY_DIR = "${WORKDIR}/tmp-xenguest" + +do_configure[noexec] = "1" +do_compile[noexec] = "1" +do_install[noexec] = "1" + +do_deploy() { + xenguest_image_clone + + # Add kernel to the image + if [ -n "${XENGUEST_IMAGE_KERNEL}" ]; then + call_xenguest_mkimage partial \ + --xen-kernel=${DEPLOY_DIR_IMAGE}/${XENGUEST_IMAGE_KERNEL} + fi + + # Pack and deploy the final image + rm -f ${DEPLOYDIR}/${XENGUEST_IMAGE_NODISK_DEPLOY} + call_xenguest_mkimage pack ${DEPLOYDIR}/${XENGUEST_IMAGE_NODISK_DEPLOY} +} +do_deploy[depends] += "virtual/kernel:do_deploy" +do_deploy[depends] += "xenguest-base-image:do_deploy" + +addtask deploy before do_build after do_install + |