diff --git a/meta-arm-autonomy/README.md b/meta-arm-autonomy/README.md index 560a783d..93b57232 100644 --- a/meta-arm-autonomy/README.md +++ b/meta-arm-autonomy/README.md @@ -41,6 +41,7 @@ its documentation. Those documentation files should be checked for variables: - [xen-devicetree](documentation/xen-devicetree.md) +- [xenguest-manager](documentation/xenguest-manager.md) BSPs ---- @@ -70,6 +71,9 @@ This layer is adding the following recipes and classes: * [xenguest-mkimage](documentation/xenguest-mkimage.md): this is a tool to create and modify images to be used as Xen guests. +* [xenguest-manager](documentation/xenguest-manager.md): this is a tool to + create/remove/start/stop xen guest generated using xenguest-mkimage. + Contributing ------------ This project has not put in place a process for contributions currently. If you diff --git a/meta-arm-autonomy/documentation/xenguest-manager.md b/meta-arm-autonomy/documentation/xenguest-manager.md new file mode 100644 index 00000000..387af944 --- /dev/null +++ b/meta-arm-autonomy/documentation/xenguest-manager.md @@ -0,0 +1,67 @@ +Xenguest Manager +================ + +Introduction +------------ + +xenguest-manager is a tool to manage Xenguest images generated by +[xenguest-mkimage](xenguest-mkimage.md). + +On a Xen Dom0 system it will: +- create a xen guest from a xenguest image: extract its components, create a + disk for the guest using LVM volumes. +- start/stop a xen guest (during init or using xenguest-manager directly). +- check guest status + +xenguest-manager is composed of 2 shell scripts: +- xenguest-manager which can be used from command line to start/stop/check +guests and create or remove guest using xenguest images. +- xenguest-init which is called during init to automatically create and start +some guests as part of the host init process. + +Usage +----- + +xenguest-manager must be called like this: +`xenguest-manager OPERATION [OPTIONS]` +The following operations are available: +- create XENGUEST_IMAGE [GUESTNAME]: create a guest from a xenguest image file + as guest GUESTNAME. If GUESTNAME is not given the image file name is used + without the xenguest extension. +- remove GUESTNAME: remove the guest GUESTNAME. +- start GUESTNAME: start the guest GUESTNAME. +- stop GUESTNAME: stop the guest GUESTNAME (this is using `xl stop` which is + sending a stop signal to the running guest). +- kill GUESTNAME: force stopping the guest GUESTNAME. +- list: list the available guests. +- status [GUESTNAME]: print the current status of GUESTNAME. If GUESTNAME is + not given, print the status of all guests. + +For a detailed help on available options please use: +`xenguest-manager --help` + +Bitbake parameters +------------------ + +Several parameters are available to configure the xenguest manager during Yocto +project compilation (those can be set in your project local.conf, for example). + +The following parameters are available: + +- XENGUEST_MANAGER_VOLUME_DEVICE: This is the device path used by the + xenguest-manager on the device to create LVM disks when guests have a disk + configuration. + This is set by default to "/dev/sda2". + +- XENGUEST_MANAGER_VOLUME_NAME: This is the LVM volume name that the + xenguest-manager will create and use to create guest LVM disks. + This is set by default to "vg-xen". + +- XENGUEST_MANAGER_GUEST_DIR: This is the directory on Dom0 where the + xenguest-manager will look for xenguest images to create during init. That's + the place where xenguest images can be added to have them automatically + created during next Dom0 boot. The xenguests found there will only be created + if they were not already before (the basename of the files is used as guest + name). + This is set by default to "/usr/share/guests". + diff --git a/meta-arm-autonomy/recipes-core/images/arm-autonomy-host-image-minimal.bb b/meta-arm-autonomy/recipes-core/images/arm-autonomy-host-image-minimal.bb index 5e09eac1..ffe5bce4 100644 --- a/meta-arm-autonomy/recipes-core/images/arm-autonomy-host-image-minimal.bb +++ b/meta-arm-autonomy/recipes-core/images/arm-autonomy-host-image-minimal.bb @@ -16,6 +16,7 @@ IMAGE_INSTALL += " \ kernel-modules \ xen-base \ qemu \ + xenguest-manager \ " # Build xen-devicetree to produce a xen ready devicetree diff --git a/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-init b/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-init new file mode 100755 index 00000000..9563d2fc --- /dev/null +++ b/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/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-manager b/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-manager new file mode 100755 index 00000000..1daebc1b --- /dev/null +++ b/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-manager @@ -0,0 +1,640 @@ +#!/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:" + +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 + +function usage() { + cat < /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 + + # Sometimes it takes time to see the device + if [ ! -b /dev/xvda${part} ]; then + sleep 1 + fi + 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) + # dd into partition + echo "xenguest-mkimage extract-disk-file ${guestfile} " \ + "${content} | dd of=/dev/xvda${part} " >> ${LOGFILE} 2>&1 + xenguest-mkimage extract-disk-file ${guestfile} ${content} \ + | 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/meta-arm-autonomy/recipes-extended/xenguest/xenguest-manager.bb b/meta-arm-autonomy/recipes-extended/xenguest/xenguest-manager.bb new file mode 100644 index 00000000..9affae9a --- /dev/null +++ b/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-xl parted e2fsprogs" + +FILES_${PN} += "${bindir}/xenguest-manager \ + ${sysconfdir}/xenguest" diff --git a/meta-arm-autonomy/recipes-extended/xenguest/xenguest-manager.bbappend b/meta-arm-autonomy/recipes-extended/xenguest/xenguest-manager.bbappend new file mode 100644 index 00000000..874cfede --- /dev/null +++ b/meta-arm-autonomy/recipes-extended/xenguest/xenguest-manager.bbappend @@ -0,0 +1,6 @@ +# Board specific configuration for the manager + +# FVP and Foundation are using vda as hard drive and partition 2 is the +# default rootfs, so use vda3 for guest lvm +XENGUEST_MANAGER_VOLUME_DEVICE_foundation-armv8 ?= "/dev/vda3" +XENGUEST_MANAGER_VOLUME_DEVICE_fvp-base ?= "/dev/vda3"