All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] arm-autonomy: Introduce Xenguest system
@ 2020-03-27 10:52 Bertrand Marquis
  2020-03-27 10:52 ` [PATCH 1/7] arm-autonomy: Create xenguest-mkimage Bertrand Marquis
                   ` (6 more replies)
  0 siblings, 7 replies; 15+ messages in thread
From: Bertrand Marquis @ 2020-03-27 10:52 UTC (permalink / raw)
  To: meta-arm; +Cc: nd

This patch serie is introducing the Xenguest system. It is introducing
an image format to store a complete xen Guest inside one image file.
The serie is adding Yocto recipes to create such images when building a
Yocto image.
It is also providing tools to use such images in a Xen Dom0.

Bertrand Marquis (7):
  arm-autonomy: Create xenguest-mkimage
  arm-autonomy: Create xenguest-manager
  arm-autonomy: Create xenguest-image class
  arm-autonomy: Create xenguest-base-image recipe
  arm-autonomy: Create xenguest image type
  arm-autonomy: Create xenguest-image-extra class
  arm-autonomy: Create xenguest-nodisk-image recipe

 meta-arm-autonomy/README.md                   |   7 +
 .../classes/image_types_xenguest.bbclass      | 132 +++
 .../classes/xenguest-image-extra.bbclass      | 102 +++
 .../classes/xenguest-image.bbclass            | 187 +++++
 .../distro/include/arm-autonomy-guest.inc     |   4 +
 .../documentation/xenguest-manager.md         |  67 ++
 .../documentation/xenguest-mkimage.md         | 119 +++
 .../images/arm-autonomy-host-image-minimal.bb |   1 +
 .../xenguest/files/xenguest-init              |  85 ++
 .../xenguest/files/xenguest-manager           | 640 +++++++++++++++
 .../xenguest/files/xenguest-mkimage           | 770 ++++++++++++++++++
 .../xenguest/xenguest-base-image.bb           | 116 +++
 .../xenguest/xenguest-manager.bb              |  52 ++
 .../xenguest/xenguest-manager.bbappend        |   6 +
 .../xenguest/xenguest-mkimage.bb              |  31 +
 .../xenguest/xenguest-nodisk-image.bb         |  38 +
 16 files changed, 2357 insertions(+)
 create mode 100644 meta-arm-autonomy/classes/image_types_xenguest.bbclass
 create mode 100644 meta-arm-autonomy/classes/xenguest-image-extra.bbclass
 create mode 100644 meta-arm-autonomy/classes/xenguest-image.bbclass
 create mode 100644 meta-arm-autonomy/documentation/xenguest-manager.md
 create mode 100644 meta-arm-autonomy/documentation/xenguest-mkimage.md
 create mode 100755 meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-init
 create mode 100755 meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-manager
 create mode 100755 meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-mkimage
 create mode 100644 meta-arm-autonomy/recipes-extended/xenguest/xenguest-base-image.bb
 create mode 100644 meta-arm-autonomy/recipes-extended/xenguest/xenguest-manager.bb
 create mode 100644 meta-arm-autonomy/recipes-extended/xenguest/xenguest-manager.bbappend
 create mode 100644 meta-arm-autonomy/recipes-extended/xenguest/xenguest-mkimage.bb
 create mode 100644 meta-arm-autonomy/recipes-extended/xenguest/xenguest-nodisk-image.bb

-- 
2.17.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/7] arm-autonomy: Create xenguest-mkimage
  2020-03-27 10:52 [PATCH 0/7] arm-autonomy: Introduce Xenguest system Bertrand Marquis
@ 2020-03-27 10:52 ` Bertrand Marquis
  2020-03-27 15:26   ` [meta-arm] " Diego Sueiro
  2020-03-27 10:52 ` [PATCH 2/7] arm-autonomy: Create xenguest-manager Bertrand Marquis
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Bertrand Marquis @ 2020-03-27 10:52 UTC (permalink / raw)
  To: meta-arm; +Cc: nd

Create a xenguest-mkimage tool to create Xen guest images.
Add documentation to explain what is a xenguest-image and how to use
xenguest-mkimage.

Change-Id: Id87240a4dfac2723f1dcceb8bfe969a7633ef261
Issue-Id: SCM-767
Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>
---
 meta-arm-autonomy/README.md                   |   3 +
 .../documentation/xenguest-mkimage.md         | 119 +++
 .../xenguest/files/xenguest-mkimage           | 770 ++++++++++++++++++
 .../xenguest/xenguest-mkimage.bb              |  31 +
 4 files changed, 923 insertions(+)
 create mode 100644 meta-arm-autonomy/documentation/xenguest-mkimage.md
 create mode 100755 meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-mkimage
 create mode 100644 meta-arm-autonomy/recipes-extended/xenguest/xenguest-mkimage.bb

diff --git a/meta-arm-autonomy/README.md b/meta-arm-autonomy/README.md
index 78a7281..560a783 100644
--- a/meta-arm-autonomy/README.md
+++ b/meta-arm-autonomy/README.md
@@ -67,6 +67,9 @@ This layer is adding the following recipes and classes:
 * [xen-devicetree](documentation/xen-devicetree.md): this is a recipe to modify
   a device tree blob to add information required to boot xen and a Dom0 linux.
 
+* [xenguest-mkimage](documentation/xenguest-mkimage.md): this is a tool to
+  create and modify images to be used as Xen guests.
+
 Contributing
 ------------
 This project has not put in place a process for contributions currently. If you
diff --git a/meta-arm-autonomy/documentation/xenguest-mkimage.md b/meta-arm-autonomy/documentation/xenguest-mkimage.md
new file mode 100644
index 0000000..d77fd48
--- /dev/null
+++ b/meta-arm-autonomy/documentation/xenguest-mkimage.md
@@ -0,0 +1,119 @@
+Xenguest mkimage
+================
+
+Introduction
+------------
+
+xenguest-mkimage is a tool to create and modify images to be used as Guest with
+Xen. It defines a format to store completely defined guests as a file or as
+a directory and provides options to create and modify those images.
+
+A xenguest image contains all elements required to create a xen guest.
+This is the base elements like a Xen configuration and a Linux kernel binary
+but also some more advanced elements like init scripts or a disk definition.
+
+The format is made to be deployable easily by storing everything in a single
+file and provide tools to easily manipulate the images. It can also easily be
+extended to have features like encryption or signature of images, updates or
+complex configurations by providing features to have init script that will be
+executed on the host embedded inside the image.
+
+Xenguest images content
+-----------------------
+
+### params.cfg
+
+This file contains parameters that can be used by tools to configure some
+functionalities on the host. This can be used by init scripts to have
+configurable parameters as it is sourced before calling init scripts.
+
+### guest.cfg and guest.d
+
+guest.cfg is the main xen configuration and guest.d contains optional
+configuration parts. All those will be merged into one final xen configuration
+before starting the guest.
+
+### files
+This directory contains files that can be used by the xen configuration, for
+example the binary of the kernel referenced in xen configuration).
+This is where the kernel binary, the dtb or a ramdisk will be stored.
+
+### init.pre, init.d and init.post
+These directories contain init scripts that will be executed on the host
+during the guest startup. Those must be shell scripts and each directory
+contains scripts called at a different time:
+ - init.pre: scripts executed before the guest is created. This can be used
+     to prepare some features required to create the guest in xen or to
+     generate part of the xen configuration dynamically.
+ - init.d: scripts executed when the guest has been created but before it is
+     started. This can be used to do some xenstore operations or configure the
+     guest behaviour using xl, for example.
+ - init.post: scripts executed just after starting the guest. This can be
+     used to configure things created by xen for the guest like network
+     network interfaces.
+
+When a directory contains several scripts, those will be called in alphabetical
+order.
+
+### disk.cfg and disk-files
+disk.cfg contains the guest disk description (disk size and disk partitions).
+The file contains the following entries:
+- `DISK_SIZE=X`: size of the disk to create in GB
+- `DISK_PARTX=SIZE:FS:CONTENT`: create a partition number X (1 to 4) with a
+  size of SIZE GB, format it with filesystem FS (can be ext2, ext3, ext4, vfat
+  or swap) and extract CONTENT as initial partition content
+  (.tar[.gz|.xz|.bz2] file or img file to be dumped in the partition). FS and
+  CONTENT can be empty.
+
+The disk-files contain files to be used for initializing the disk partitions
+content. Those should be used to create a LVM or a physical disk and initialize
+it (create partitions, format them and put the initial content).
+
+Usage
+-----
+
+xenguest-mkimage is a shell script which must be called like this:
+`xenguest-mkimage OPERATION XENGUEST [OPTIONS]`
+
+### Operations
+- create: create a xenguest image. If XENGUEST is an existing empty directory,
+  the image is created as a directory otherwise it will be created as a file.
+- check: verify that XENGUEST is a valid xenguest image.
+- update: modify a xenguest image (see --help for a list of operations).
+- pack: pack a xenguest image directory into a xenguest image file. The file to
+  be created must be given as 3rd argument.
+- extract: extract a xenguest image file into a directory. The destination
+  directory must be given as 3rd argument.
+- dump-xenconfig: dump xenguest image xen configuration.
+- dump-diskconfig: dump xenguest image disk configuration.
+- dump-paramsconfig: dump xenguest image parameters configuration.
+
+For a detailed help on available operations, please use:
+`xenguest-mkimage --help`
+
+### Options
+- --kernel=FILE: add kernel FILE as guest kernel. This is both adding the file
+  to the image and modifying the xen configuration to use it.
+- --xen-memory=SIZE: set the guest memory size in MB.
+- --xen-extra: add a kernel command line argument. This can be called several
+  times to add several command line options.
+- --xen-device-tree=FILE: add dtb FILE as device tree. This both adding the
+  file to the image and modifying the xen configuration to use it.
+- --init-script=FILE: add guest init script. The script is embedded inside the
+  image file. Several script can be added and the basename of FILE is used to
+  distinguish them (calling the option twice with the same file will update the
+  script in the image with the second one).
+ --disk-size=SIZE: set the guest disk size to SIZE in GB. Calling this with 0
+  disable the guest disk.
+- --disk-add-part=NUM:SIZE:FS:CONTENT: This is adding a partition to the
+  xenguest image disk. The partition is described with the arguments:
+  - NUM: partition number.
+  - SIZE: partition size in GB.
+  - FS: filesystem to format the partition with. This can be ext2, ext3, ext4,
+    vfat of swap. If empty the partition is not formated.
+  - CONTENT: tar of img file to use to initialize the partition. The file must
+    be added to the image using --disk-add-file=FILE:CONTENT.
+
+For a detailed help on available options, please use:
+`xenguest-mkimage OPERATION --help`
+
diff --git a/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-mkimage b/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-mkimage
new file mode 100755
index 0000000..58fcd01
--- /dev/null
+++ b/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-mkimage
@@ -0,0 +1,770 @@
+#!/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)
+                         - 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() {
+    partid=${1}
+    partsize=${2}
+    partfs=${3}
+    partcont=${4:-}
+
+    # Make we don't add the same partition twice
+    disk_config_rm_part ${partid}
+    echo "DISK_PART${partid}=\"${partsize}:${partfs}:${partcont}\"" >> \
+        ${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 ./guest.d
+        else
+            cat ${guestfile}/guest.cfg ${guestfile}/guest.d/*
+        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: Cannot pack a xenguest image"
+            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 config extract"
+            exit 1
+        fi
+
+        tar -C ${1} -xf ${guestfile}
+        exit 0
+        ;;
+    extract-config)
+        check_image ${guestfile}
+        if [ ! -f ${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 [ ! -f ${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 $(echo "${optarg}" | tr ":" " ")
+            ;;
+        --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/meta-arm-autonomy/recipes-extended/xenguest/xenguest-mkimage.bb b/meta-arm-autonomy/recipes-extended/xenguest/xenguest-mkimage.bb
new file mode 100644
index 0000000..6ea5fb1
--- /dev/null
+++ b/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"
+
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/7] arm-autonomy: Create xenguest-manager
  2020-03-27 10:52 [PATCH 0/7] arm-autonomy: Introduce Xenguest system Bertrand Marquis
  2020-03-27 10:52 ` [PATCH 1/7] arm-autonomy: Create xenguest-mkimage Bertrand Marquis
@ 2020-03-27 10:52 ` Bertrand Marquis
  2020-03-27 15:27   ` [meta-arm] " Diego Sueiro
  2020-03-27 10:52 ` [PATCH 3/7] arm-autonomy: Create xenguest-image class Bertrand Marquis
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Bertrand Marquis @ 2020-03-27 10:52 UTC (permalink / raw)
  To: meta-arm; +Cc: nd

Add xenguest-manager to handle xenguest image based guests:
- create guest (use LVM to create disks for guests)
- start/stop guests
- provide init script to have guest auto started on boot
- add documentation

Change-Id: I5319ecb77f3aa9f8c1aff4891c05973288156f11
Issue-Id: SCM-767
Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>
---
 meta-arm-autonomy/README.md                   |   4 +
 .../documentation/xenguest-manager.md         |  67 ++
 .../images/arm-autonomy-host-image-minimal.bb |   1 +
 .../xenguest/files/xenguest-init              |  85 +++
 .../xenguest/files/xenguest-manager           | 640 ++++++++++++++++++
 .../xenguest/xenguest-manager.bb              |  52 ++
 .../xenguest/xenguest-manager.bbappend        |   6 +
 7 files changed, 855 insertions(+)
 create mode 100644 meta-arm-autonomy/documentation/xenguest-manager.md
 create mode 100755 meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-init
 create mode 100755 meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-manager
 create mode 100644 meta-arm-autonomy/recipes-extended/xenguest/xenguest-manager.bb
 create mode 100644 meta-arm-autonomy/recipes-extended/xenguest/xenguest-manager.bbappend

diff --git a/meta-arm-autonomy/README.md b/meta-arm-autonomy/README.md
index 560a783..93b5723 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 0000000..387af94
--- /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 5e09eac..ffe5bce 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 0000000..9563d2f
--- /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 0000000..1daebc1
--- /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 <<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()
+{
+    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
+
+            # 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 0000000..9affae9
--- /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 0000000..874cfed
--- /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"
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/7] arm-autonomy: Create xenguest-image class
  2020-03-27 10:52 [PATCH 0/7] arm-autonomy: Introduce Xenguest system Bertrand Marquis
  2020-03-27 10:52 ` [PATCH 1/7] arm-autonomy: Create xenguest-mkimage Bertrand Marquis
  2020-03-27 10:52 ` [PATCH 2/7] arm-autonomy: Create xenguest-manager Bertrand Marquis
@ 2020-03-27 10:52 ` Bertrand Marquis
  2020-03-27 15:27   ` [meta-arm] " Diego Sueiro
  2020-03-27 10:52 ` [PATCH 4/7] arm-autonomy: Create xenguest-base-image recipe Bertrand Marquis
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Bertrand Marquis @ 2020-03-27 10:52 UTC (permalink / raw)
  To: meta-arm; +Cc: nd

Create xenguest-image class to be used by recipes and other classes to
manipulate xenguest images.
The recipe is defining some variables to configure default parameters of
xenguest image (memory size, number of vcpus, command line, etc.). Those
parameters all have the prefix XENGUEST_IMAGE_ and are documented at the
beginning of the class.

The class also provide some helper functions:
- xenguest_image_create to create a xenguest image (using global
parameters) in deploy as xenguest image directory
- xenguest_image_clone to clone current xenguest image from deploy to be
able to extend it and pack it in a xenguest image file
- xenguest_image_rootfs_file function to allow other recipes to detect
if the rootfs should or not be embedded in the xenguest image

Change-Id: I4ba54aa2c41e72964c152f673b71fe32f30b4aca
Issue-Id: SCM-767
Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>
---
 .../classes/xenguest-image.bbclass            | 187 ++++++++++++++++++
 1 file changed, 187 insertions(+)
 create mode 100644 meta-arm-autonomy/classes/xenguest-image.bbclass

diff --git a/meta-arm-autonomy/classes/xenguest-image.bbclass b/meta-arm-autonomy/classes/xenguest-image.bbclass
new file mode 100644
index 0000000..fecf1ae
--- /dev/null
+++ b/meta-arm-autonomy/classes/xenguest-image.bbclass
@@ -0,0 +1,187 @@
+# This class must be used to create, extend or pack a xenguest image.
+# It is using xenguest-mkimage tool to do operations
+
+DEPENDS += "xenguest-mkimage-native"
+
+#
+# Xenguest image parameters
+# All the following parameters can be modified in local.conf or on recipes
+# inheriting this class
+#
+
+# Guest memory size in MB
+XENGUEST_IMAGE_MEMORY_SIZE ??= "512"
+
+# Guest number of vcpus
+XENGUEST_IMAGE_NUM_VCPUS ??= "1"
+
+# Guest auto boot during init, set to 1 to have guest started during init or
+# to 0 if the guest should not be auto started
+XENGUEST_IMAGE_AUTOBOOT ??= "1"
+
+# Partition containing the root file system
+# Xen will actually add root=${XENGUEST_IMAGE_ROOT} to your guest kernel
+# command line
+# You can let this empty if the root filesystem is specified in an other way
+# and have root= option added to the command line for example or if you don't
+# need a root filesystem mounted for your guest (initrd for example)
+XENGUEST_IMAGE_ROOT ??= "/dev/xvda1"
+
+# Guest kernel command line arguments
+XENGUEST_IMAGE_CMDLINE ??= "earlyprintk=xenboot console=hvc0 rw"
+
+# Extra commands to add to xenguest-image when creating the image
+XENGUEST_IMAGE_EXTRA_CMD ??= ""
+
+# Kernel binary
+# This value is used by the xenguest image type but is declared here to have
+# all variables in the same place
+# Default value is:
+# - Image if INITRAMFS_IMAGE is not set
+# - Image-initramfs-${MACHINE}.bin if INITRAMFS_IMAGE is set
+# If this value is empty no kernel will be added to the image
+XENGUEST_IMAGE_KERNEL ??= "${@ 'Image' if not d.getVar('INITRAMFS_IMAGE') else 'Image-initramfs-${MACHINE}.bin'}"
+
+# Size of the disk to create (if 0 no disk will be created and rootfs will not
+# be included in the xenguest image)
+XENGUEST_IMAGE_DISK_SIZE ??= "${@ '4' if not d.getVar('INITRAMFS_IMAGE') else '0'}"
+
+#
+# XENGUEST_IMAGE_DISK PARTITIONS is used to describe the partitions to setup
+# and their content.
+# It must be set to a space separated list of entries with each entry having
+# the format num:sz:fs:[file] where:
+# - num is a partition number
+# - sz is the partition size in Gigabit
+# - fs is the filesystem to use for the partition
+# - file is optionally pointing to a file to use as content of the partition
+#   Please check image_types_xenguest.bbclass for rootfs handling of files
+#
+# Default value creates a partition 1 using the full disk, formated with ext4
+# and containing the root filesystem produced by Yocto
+XENGUEST_IMAGE_DISK_PARTITIONS ??= "1:${XENGUEST_IMAGE_DISK_SIZE}:ext4:rootfs.tar.gz"
+
+# Sub-directory in wich the guest is created. This is create in deploy as a
+# subdirectory and must be coherent between all components using this class so
+# it must only be modified from local.conf if needed
+XENGUEST_IMAGE_DEPLOY_SUBDIR ?= "xenguest"
+
+# Directory in which the xenguest should be deployed
+# a sub-directory named ${XENGUEST_IMAGE_DEPLOY_SUBDIR} will be created there.
+# This should be set to:
+# - ${DEPLOYDIR} (default) if creating or extending the xenguest for a normal
+#   recipe.
+# - something in ${WORKDIR} if you need to clone and manipulate an image
+XENGUEST_IMAGE_DEPLOY_DIR ??= "${DEPLOYDIR}"
+
+#
+# Wrapper to call xenguest-mkimage
+# It is using XENGUEST_IMAGE_DEPLOY_DIR and XENGUEST_IMAGE_DEPLOY_SUBDIR
+# to find the image to operate on
+#
+# Usage: call_xenguest_mkimage [operation] [args]
+call_xenguest_mkimage() {
+    local cmd="${1}"
+    local img="${XENGUEST_IMAGE_DEPLOY_DIR}/${XENGUEST_IMAGE_DEPLOY_SUBDIR}"
+    shift
+
+    echo "xenguest-mkimage $cmd $img $@"
+    xenguest-mkimage $cmd $img $@
+}
+
+#
+# Create an initial xenguest image.
+# This is a task which must be added in a recipe inheriting deploy
+# It is using XENGUEST_IMAGE_MEMORY_SIZE, XENGUEST_IMAGE_NUM_VCPUS,
+#  XENGUEST_IMAGE_AUTOBOOT, XENGUEST_IMAGE_ROOT, XENGUEST_IMAGE_EXTRA_CMD,
+#  XENGUEST_IMAGE_CMDLINE, XENGUEST_IMAGE_DISK_SIZE and
+#  XENGUEST_IMAGE_DISK_PARTITIONS to customize the initial guest
+#
+xenguest_image_create() {
+    if [ -z "${XENGUEST_IMAGE_DEPLOY_DIR}" -o \
+        -z "${XENGUEST_IMAGE_DEPLOY_SUBDIR}" ]; then
+        die "Configuration error: XENGUEST_IMAGE_DEPLOY_DIR or XENGUEST_IMAGE_DEPLOY_SUBDIR is empty"
+    fi
+
+    rm -rf ${XENGUEST_IMAGE_DEPLOY_DIR}/${XENGUEST_IMAGE_DEPLOY_SUBDIR}
+
+    mkdir -p ${XENGUEST_IMAGE_DEPLOY_DIR}/${XENGUEST_IMAGE_DEPLOY_SUBDIR}
+
+    # Create the image
+    call_xenguest_mkimage create --xen-memory=${XENGUEST_IMAGE_MEMORY_SIZE} \
+        --xen-vcpus=${XENGUEST_IMAGE_NUM_VCPUS} \
+        --xen-root=${XENGUEST_IMAGE_ROOT} \
+        ${XENGUEST_IMAGE_EXTRA_CMD}
+
+    # add command line
+    if [ -n "${XENGUEST_IMAGE_CMDLINE}" ]; then
+        call_xenguest_mkimage update --xen-clean-extra
+        for arg in ${XENGUEST_IMAGE_CMDLINE}; do
+            call_xenguest_mkimage update --xen-extra=$arg
+        done
+    fi
+
+    # create disk if needed
+    disksize="${XENGUEST_IMAGE_DISK_SIZE}"
+    if [ -z "$disksize" ]; then
+        disksize="0"
+    fi
+    if [ $disksize -gt 0 ]; then
+        # setup disk size
+        call_xenguest_mkimage update --disk-reset-config --disk-size=$disksize
+
+        diskparts="${XENGUEST_IMAGE_DISK_PARTITIONS}"
+        if [ -n "$diskparts" ]; then
+            for arg in $diskparts; do
+                call_xenguest_mkimage update --disk-add-part=$arg
+                partnum="$(expr $partnum + 1)"
+            done
+        fi
+    fi
+
+    if [ "${XENGUEST_IMAGE_AUTOBOOT}" = "1" ]; then
+        call_xenguest_mkimage update --set-param=GUEST_AUTOBOOT=1
+    else
+        call_xenguest_mkimage update --set-param=GUEST_AUTOBOOT=0
+    fi
+}
+
+#
+# Clone the current xenguest from deploy to manipulate it locally
+# This is required if you need to change things before packing an image
+# To set the local directory where to clone you must set
+# XENGUEST_IMAGE_DEPLOY_DIR if you don't want to use do_deploy to modify the
+# image
+#
+xenguest_image_clone() {
+    if [ -z "${XENGUEST_IMAGE_DEPLOY_DIR}" -o \
+        -z "${XENGUEST_IMAGE_DEPLOY_SUBDIR}" ]; then
+        die "Configuration error: XENGUEST_IMAGE_DEPLOY_DIR or XENGUEST_IMAGE_DEPLOY_SUBDIR is empty"
+    fi
+
+    if [ ! -f ${DEPLOY_DIR_IMAGE}/${XENGUEST_IMAGE_DEPLOY_SUBDIR}/guest.cfg ]; then
+        die "xenguest-image: ${DEPLOY_DIR_IMAGE}/${XENGUEST_IMAGE_DEPLOY_SUBDIR} does not contain a valid guest"
+    fi
+
+    rm -rf ${XENGUEST_IMAGE_DEPLOY_DIR}/${XENGUEST_IMAGE_DEPLOY_SUBDIR}
+    mkdir -p ${XENGUEST_IMAGE_DEPLOY_DIR}
+    cp -rf ${DEPLOY_DIR_IMAGE}/${XENGUEST_IMAGE_DEPLOY_SUBDIR} \
+        ${XENGUEST_IMAGE_DEPLOY_DIR}/${XENGUEST_IMAGE_DEPLOY_SUBDIR}
+}
+
+# Helper function to retrieve rootfs file if present in one partition
+# This can return an empty string or rootfs.tar[.COMP]
+def xenguest_image_rootfs_file(d):
+    disksize = d.getVar('XENGUEST_IMAGE_DISK_SIZE')
+    # if disksize is 0, we don't create anything
+    if not disksize or disksize == '0':
+        return ""
+    # Find first partition with file=rootfs.tar*
+    partlist = d.getVar('XENGUEST_IMAGE_DISK_PARTITIONS')
+    if partlist:
+        for partdesc in partlist.split():
+            partelems = partdesc.split(':', 3)
+            if partelems[3]:
+                if partelems[3].startswith('rootfs.tar'):
+                    return partelems[3]
+    return ""
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/7] arm-autonomy: Create xenguest-base-image recipe
  2020-03-27 10:52 [PATCH 0/7] arm-autonomy: Introduce Xenguest system Bertrand Marquis
                   ` (2 preceding siblings ...)
  2020-03-27 10:52 ` [PATCH 3/7] arm-autonomy: Create xenguest-image class Bertrand Marquis
@ 2020-03-27 10:52 ` Bertrand Marquis
  2020-03-27 15:28   ` [meta-arm] " Diego Sueiro
  2020-03-27 10:52 ` [PATCH 5/7] arm-autonomy: Create xenguest image type Bertrand Marquis
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Bertrand Marquis @ 2020-03-27 10:52 UTC (permalink / raw)
  To: meta-arm; +Cc: nd

Add xenguest-base-image recipe to create an initial xenguest image
directory in deploy.
This is using the xenguest-image class.
The recipe is also introducing several parameters named
XENGUEST_IMAGE_SRC_URI_* to allow the user to specify files or elements
to be added to the xenguest image.
Those parameters are documented inside the recipe.

Change-Id: I806a2fa07fb9593c366d88e2f4ee8b649cbcf8ea
Issue-Id: SCM-767
Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>
---
 .../xenguest/xenguest-base-image.bb           | 116 ++++++++++++++++++
 1 file changed, 116 insertions(+)
 create mode 100644 meta-arm-autonomy/recipes-extended/xenguest/xenguest-base-image.bb

diff --git a/meta-arm-autonomy/recipes-extended/xenguest/xenguest-base-image.bb b/meta-arm-autonomy/recipes-extended/xenguest/xenguest-base-image.bb
new file mode 100644
index 0000000..ea4a9f3
--- /dev/null
+++ b/meta-arm-autonomy/recipes-extended/xenguest/xenguest-base-image.bb
@@ -0,0 +1,116 @@
+# 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 you download 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 ??= ""
+
+# Add init script
+
+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"
+
+    if [ -d ${WORKDIR}/extend/$subdir ]; then
+        filelist=$(find ${WORKDIR}/extend/$subdir -type f)
+
+        if [ -n "$filelist" ]; then
+            for f in $filelist; do
+                call_xenguest_mkimage update --$cmd=$f:$(basename $f)
+            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"
+    add_extend_files "files" "xen-add-file"
+    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
+
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/7] arm-autonomy: Create xenguest image type
  2020-03-27 10:52 [PATCH 0/7] arm-autonomy: Introduce Xenguest system Bertrand Marquis
                   ` (3 preceding siblings ...)
  2020-03-27 10:52 ` [PATCH 4/7] arm-autonomy: Create xenguest-base-image recipe Bertrand Marquis
@ 2020-03-27 10:52 ` Bertrand Marquis
  2020-03-27 15:28   ` [meta-arm] " Diego Sueiro
  2020-03-27 10:52 ` [PATCH 6/7] arm-autonomy: Create xenguest-image-extra class Bertrand Marquis
  2020-03-27 10:52 ` [PATCH 7/7] arm-autonomy: Create xenguest-nodisk-image recipe Bertrand Marquis
  6 siblings, 1 reply; 15+ messages in thread
From: Bertrand Marquis @ 2020-03-27 10:52 UTC (permalink / raw)
  To: meta-arm; +Cc: nd

Create an image type xenguest to create a xenguest image as part of a
Yocto image (add FSTYPE xenguest).

The image type is using xenguest-base-image as a producer for the
xenguest image directory, adds kernel defined by
XENGUEST_IMAGE_KERNEL to it, adds rootfs if listed in
XENGUEST_IMAGE_DISK_PARTITIONS and pack the final image with file
extension .xenguest with other types of images.

If initramfs is configured, a xenguest image containing the kernel with
initramfs is produced.

The xenguest image type is added to IMAGE_FSTYPES and IMAGE_CLASSES if
arm-autonomy-guest is set in DISTRO_FEATURES.

Change-Id: Ibae8a50d41375839492e43a2e28d9472dc71b4a1
Issue-Id: SCM-767
Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>
---
 .../classes/image_types_xenguest.bbclass      | 132 ++++++++++++++++++
 .../distro/include/arm-autonomy-guest.inc     |   4 +
 2 files changed, 136 insertions(+)
 create mode 100644 meta-arm-autonomy/classes/image_types_xenguest.bbclass

diff --git a/meta-arm-autonomy/classes/image_types_xenguest.bbclass b/meta-arm-autonomy/classes/image_types_xenguest.bbclass
new file mode 100644
index 0000000..ff1e41a
--- /dev/null
+++ b/meta-arm-autonomy/classes/image_types_xenguest.bbclass
@@ -0,0 +1,132 @@
+# Create a xenguest image with kernel and filesystem produced by Yocto
+# This will create a .xenguest file that the xenguest-manager can use.
+
+inherit xenguest-image deploy
+
+# We are creating our guest in a local subdirectory
+# force the value so that we are not impacted if the user is changing it
+XENGUEST_IMAGE_DEPLOY_DIR = "${WORKDIR}/tmp-xenguest"
+
+# Name of deployed file (keep standard image name and add .xenguest)
+XENGUEST_IMAGE_DEPLOY ??= "${IMAGE_NAME}"
+
+# Deployed file when building with initramfs
+XENGUEST_IMAGE_INITRAMFS_DEPLOY ??= "Image-initramfs-${MACHINE}"
+
+# Add kernel XENGUEST_IMAGE_KERNEL from DEPLOY_DIR_IMAGE to image
+xenguest_image_add_kernel() {
+    srcfile="${1:-}"
+    if [ -z "${srcfile}" ]; then
+        srcfile="${DEPLOY_DIR_IMAGE}/${XENGUEST_IMAGE_KERNEL}"
+    fi
+    call_xenguest_mkimage partial --xen-kernel=$srcfile
+}
+
+# Add rootfs file to the image
+xenguest_image_add_rootfs() {
+    call_xenguest_mkimage partial \
+        --disk-add-file=${IMGDEPLOYDIR}/${IMAGE_LINK_NAME}.${IMAGE_TYPEDEP_xenguest}:rootfs.${IMAGE_TYPEDEP_xenguest}
+}
+
+# Pack xenguest image
+xenguest_image_pack() {
+    mkdir -p ${IMGDEPLOYDIR}
+    rm -f ${IMGDEPLOYDIR}/${XENGUEST_IMAGE_DEPLOY}.xenguest
+    call_xenguest_mkimage pack \
+        ${IMGDEPLOYDIR}/${XENGUEST_IMAGE_DEPLOY}.xenguest
+}
+
+# do_deploy is used for initramfs to pack the kernel initramfs in an image
+do_deploy() {
+    # Add kernel
+    xenguest_image_add_kernel
+
+    # Pack the image in deploydir
+    mkdir -p ${DEPLOYDIR}
+    rm -f ${DEPLOYDIR}/${XENGUEST_IMAGE_INITRAMFS_DEPLOY}.xenguest
+    call_xenguest_mkimage pack \
+        ${DEPLOYDIR}/${XENGUEST_IMAGE_INITRAMFS_DEPLOY}.xenguest
+}
+do_deploy[depends] += "${PN}:do_bootimg_xenguest"
+do_deploy[depends] += "virtual/kernel:do_deploy"
+
+#
+# Task finishing the bootimg
+# We need this task to actually create the symlinks
+#
+python do_bootimg_xenguest() {
+    subtasks = d.getVarFlag('do_bootimg_xenguest', 'subtasks')
+
+    bb.build.exec_func('xenguest_image_clone', d)
+    if subtasks:
+        for tk in subtasks.split():
+            bb.build.exec_func(tk, d)
+    bb.build.exec_func('xenguest_image_pack', d)
+    bb.build.exec_func('create_symlinks', d)
+}
+# This is used to add sub-tasks to do_bootimg_xenguest
+do_bootimg_xenguest[subtasks] = ""
+# Those are required by create_symlinks to find our image
+do_bootimg_xenguest[subimages] = "xenguest"
+do_bootimg_xenguest[imgsuffix] = "."
+do_bootimg_xenguest[depends] += "xenguest-base-image:do_deploy"
+# Need to have rootfs so all recipes have deployed their content
+do_bootimg_xenguest[depends] += "${PN}:do_rootfs"
+
+# This set in python anonymous after, just set a default value here
+IMAGE_TYPEDEP_xenguest ?= "tar"
+
+# We must not be built at rootfs build time because we need the kernel
+IMAGE_TYPES_MASKED += "xenguest"
+IMAGE_TYPES += "xenguest"
+
+python __anonymous() {
+    # Do not do anything if we are not in the want FSTYPES
+    if bb.utils.contains_any('IMAGE_FSTYPES', 'xenguest', '1', '0', d):
+
+        # Check the coherency of the configuration
+        rootfs_needed = False
+        rootfs_file = ''
+        kernel_needed = False
+        initramfs_needed = False
+
+        rootfs_file = xenguest_image_rootfs_file(d)
+        if rootfs_file:
+            rootfs_needed = True
+
+        if d.getVar('XENGUEST_IMAGE_KERNEL'):
+            kernel_needed = True
+
+        if d.getVar('INITRAMFS_IMAGE'):
+            if int(d.getVar('INITRAMFS_IMAGE_BUNDLE')) != 1:
+                bb.error("xenguest-fstype: INITRAMFS_IMAGE is set but INITRAMFS_IMAGE_BUNDLE is set to 0.\n")
+                bb.fatal("xenguest-fstype: This configuration is not supported by xenguest image type\n")
+            initramfs_needed = True
+
+        if initramfs_needed and rootfs_needed:
+            bb.warn("xenguest-fstype: Final image will use an initramfs kernel and rootfs in disk.\n")
+            bb.warn("xenguest-fstype: rootfs.tar.%s should be removed from XENGUEST_IMAGE_DISK_PARTITIONS.\n")
+
+        if not initramfs_needed and not rootfs_needed and not kernel_needed:
+            bb.warn("xenguest-fstype: Generated image will have no kernel and no rootfs.\n")
+
+        bb.build.addtask('do_bootimg_xenguest', 'do_image_complete', None, d)
+
+        if rootfs_needed:
+            # tell do_bootimg_xenguest to call add_rootfs
+            d.appendVarFlag('do_bootimg_xenguest', 'subtasks', ' xenguest_image_add_rootfs')
+            # do_bootimg_xenguest will need the tar file
+            d.appendVarFlag('do_bootimg_xenguest', 'depends', ' %s:do_image_tar' % (d.getVar('PN')))
+            # set our TYPEDEP to the proper compression
+            d.setVar('IMAGE_TYPEDEP_xenguest', 'tar' + (rootfs_file.split('.tar', 1)[1] or ''))
+
+        if kernel_needed:
+            if initramfs_needed:
+                bb.build.addtask('do_deploy', 'do_build', None, d)
+            else:
+                # Tell do_bootimg_xenguest to call xenguest_image_add_kernel
+                d.appendVarFlag('do_bootimg_xenguest', 'subtasks', ' xenguest_image_add_kernel')
+                # we will need kernel do_deploy
+                d.appendVarFlag('do_bootimg_xenguest', 'depends', ' virtual/kernel:do_deploy')
+}
+
diff --git a/meta-arm-autonomy/conf/distro/include/arm-autonomy-guest.inc b/meta-arm-autonomy/conf/distro/include/arm-autonomy-guest.inc
index d961b40..9b5889e 100644
--- a/meta-arm-autonomy/conf/distro/include/arm-autonomy-guest.inc
+++ b/meta-arm-autonomy/conf/distro/include/arm-autonomy-guest.inc
@@ -3,3 +3,7 @@
 # We need to have ipv4 activated
 DISTRO_FEATURES_append = " ipv4"
 
+# Build a xenguest type image
+IMAGE_CLASSES += "image_types_xenguest"
+IMAGE_FSTYPES += "xenguest"
+
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/7] arm-autonomy: Create xenguest-image-extra class
  2020-03-27 10:52 [PATCH 0/7] arm-autonomy: Introduce Xenguest system Bertrand Marquis
                   ` (4 preceding siblings ...)
  2020-03-27 10:52 ` [PATCH 5/7] arm-autonomy: Create xenguest image type Bertrand Marquis
@ 2020-03-27 10:52 ` Bertrand Marquis
  2020-03-27 15:28   ` [meta-arm] " Diego Sueiro
  2020-03-27 10:52 ` [PATCH 7/7] arm-autonomy: Create xenguest-nodisk-image recipe Bertrand Marquis
  6 siblings, 1 reply; 15+ messages in thread
From: Bertrand Marquis @ 2020-03-27 10:52 UTC (permalink / raw)
  To: meta-arm; +Cc: nd

Add class xenguest-image-extra to be used by recipes which wants to add
elements to the generated xenguest image.
The recipes using this call must inherit the deploy class and declare a
deploy task that will be extended by the class. The variables
XENGUEST_EXTRA_* documented in the class can be used to define what
should be used to extend the xenguest image.

Change-Id: I8a7682a7a7ca57b424ea815145408ccb8e4348ca
Issue-Id: SCM-767
Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>
---
 .../classes/xenguest-image-extra.bbclass      | 102 ++++++++++++++++++
 1 file changed, 102 insertions(+)
 create mode 100644 meta-arm-autonomy/classes/xenguest-image-extra.bbclass

diff --git a/meta-arm-autonomy/classes/xenguest-image-extra.bbclass b/meta-arm-autonomy/classes/xenguest-image-extra.bbclass
new file mode 100644
index 0000000..a5697e5
--- /dev/null
+++ b/meta-arm-autonomy/classes/xenguest-image-extra.bbclass
@@ -0,0 +1,102 @@
+# This class must be used to extend the xenguest image
+# It provides variables to add init scripts, a dtb, xen files or disk files.
+#
+# The class is extending deploy function so you recipe must inherit deploy and
+# have a do_deploy function (even if it is empty)
+
+# Use standard xenguest-image
+inherit xenguest-image
+
+# Add a DTB file for the guest
+# Only one file should be added, if this is set multiple times or in several
+# recipes, the last recipe setting it will prevail.
+XENGUEST_EXTRA_DTB ??= ""
+
+# Append something to the guest xen configuration
+# All files here will be merged together in the final xen configuration
+# This can contain several files or be used in several recipes
+XENGUEST_EXTRA_XENCONFIG ??= ""
+
+# Add a xenguest init, init-pre or init-post script
+XENGUEST_EXTRA_INIT_PRE ??= ""
+XENGUEST_EXTRA_INIT ??= ""
+XENGUEST_EXTRA_INIT_POST ??= ""
+
+# Add xenguest files, (to be used in extra xen config for example)
+# several files may be added, space separated, the path will be kept on the
+# generated xenguest image (if dir1/file1 is added, it can be used as
+# dir1/file1 file in the xen configuration).
+XENGUEST_EXTRA_FILES ??= ""
+
+# Add xenguest disk files (to be used as disk partition content)
+# several files may be added, space separated, the path will be kept on the
+# generated xenguest image (if dir1/file1 is added, it can be used as
+# dir1/file1 file in the disk content parameters).
+XENGUEST_EXTRA_DISK_FILES ??= ""
+
+do_deploy_append() {
+    if [ -z "${XENGUEST_IMAGE_DEPLOY_DIR}" -o \
+        -z "${XENGUEST_IMAGE_DEPLOY_SUBDIR}" ]; then
+        die "Configuration error: XENGUEST_IMAGE_DEPLOY_DIR or XENGUEST_IMAGE_DEPLOY_SUBDIR is empty"
+    fi
+    rm -rf ${XENGUEST_IMAGE_DEPLOY_DIR}/${XENGUEST_IMAGE_DEPLOY_SUBDIR}
+    mkdir -p ${XENGUEST_IMAGE_DEPLOY_DIR}/${XENGUEST_IMAGE_DEPLOY_SUBDIR}
+
+    if [ -n "${XENGUEST_EXTRA_DTB}" ]; then
+        if [ ! -f ${XENGUEST_EXTRA_DTB} ]; then
+            die "xenguest-image: DTB file ${XENGUEST_EXTRA_DTB} does not exist"
+        fi
+        call_xenguest_mkimage partial --xen-device-tree=${XENGUEST_EXTRA_DTB}
+    fi
+
+    if [ -n "${XENGUEST_EXTRA_XENCONFIG}" ]; then
+        for f in ${XENGUEST_EXTRA_XENCONFIG}; do
+            if [ ! -f $f ]; then
+                die "xenguest-image: Xen config $f does not exist"
+            fi
+            call_xenguest_mkimage partial --xen-append=$f
+        done
+    fi
+
+    if [ -n "${XENGUEST_EXTRA_INIT_PRE}" ]; then
+        if [ ! -f ${XENGUEST_EXTRA_INIT_PRE} ]; then
+            die "xenguest-image: Init script ${XENGUEST_EXTRA_INIT_PRE} does not exist"
+        fi
+        call_xenguest_mkimage partial --init-pre=${XENGUEST_EXTRA_INIT_PRE}
+    fi
+
+    if [ -n "${XENGUEST_EXTRA_INIT}" ]; then
+        if [ ! -f ${XENGUEST_EXTRA_INIT} ]; then
+            die "xenguest-image: Init script ${XENGUEST_EXTRA_INIT} does not exist"
+        fi
+        call_xenguest_mkimage partial --init-script=${XENGUEST_EXTRA_INIT}
+    fi
+
+    if [ -n "${XENGUEST_EXTRA_INIT_POST}" ]; then
+        if [ ! -f ${XENGUEST_EXTRA_INIT_POST} ]; then
+            die "xenguest-image: Init script ${XENGUEST_EXTRA_INIT_POST} does not exist"
+        fi
+        call_xenguest_mkimage partial --init-post=${XENGUEST_EXTRA_INIT_POST}
+    fi
+
+    if [ -n "${XENGUEST_EXTRA_FILES}" ]; then
+        for f in ${XENGUEST_EXTRA_FILES}; do
+            if [ ! -f $f ]; then
+                die "xenguest-image: Xen file $file does not exist"
+            fi
+            call_xenguest_mkimage partial --disk-add-file=$file
+        done
+    fi
+
+    if [ -n "${XENGUEST_EXTRA_DISK_FILES}" ]; then
+        for f in ${XENGUEST_EXTRA_DISK_FILES}; do
+            if [ ! -f $f ]; then
+                die "xenguest-image: Disk file $f does not exist"
+            fi
+            call_xenguest_mkimage partial --disk-add-file=$f
+        done
+    fi
+}
+# Need to have xenguest-image tool
+do_deploy[depends] += "xenguest-base-image:do_deploy"
+
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 7/7] arm-autonomy: Create xenguest-nodisk-image recipe
  2020-03-27 10:52 [PATCH 0/7] arm-autonomy: Introduce Xenguest system Bertrand Marquis
                   ` (5 preceding siblings ...)
  2020-03-27 10:52 ` [PATCH 6/7] arm-autonomy: Create xenguest-image-extra class Bertrand Marquis
@ 2020-03-27 10:52 ` Bertrand Marquis
  2020-03-27 15:29   ` [meta-arm] " Diego Sueiro
  6 siblings, 1 reply; 15+ messages in thread
From: Bertrand Marquis @ 2020-03-27 10:52 UTC (permalink / raw)
  To: meta-arm; +Cc: nd

Create a xenguest-nodisk-image recipe to be used when wanting to create
a xenguest image without packing in it a root filesystem generated by
Yocto.
This recipe can be used to use aio root filesystem from an external tar
file and just compile and take the linux kernel coming from Yocto.

To achieve this, the variable XENGUEST_IMAGE_SRC_URI_DISK_FILES should
be set to a SRC_URI compatible URL to the tar file and then call bitbake
xenguest-nodisk-image.

Change-Id: I1a8d80b89930f3bb6bcce40a55b4dfce9b5331ef
Issue-Id: SCM-767
Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>
---
 .../xenguest/xenguest-nodisk-image.bb         | 38 +++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 meta-arm-autonomy/recipes-extended/xenguest/xenguest-nodisk-image.bb

diff --git a/meta-arm-autonomy/recipes-extended/xenguest/xenguest-nodisk-image.bb b/meta-arm-autonomy/recipes-extended/xenguest/xenguest-nodisk-image.bb
new file mode 100644
index 0000000..b2dbbe9
--- /dev/null
+++ b/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
+
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [meta-arm] [PATCH 1/7] arm-autonomy: Create xenguest-mkimage
  2020-03-27 10:52 ` [PATCH 1/7] arm-autonomy: Create xenguest-mkimage Bertrand Marquis
@ 2020-03-27 15:26   ` Diego Sueiro
  0 siblings, 0 replies; 15+ messages in thread
From: Diego Sueiro @ 2020-03-27 15:26 UTC (permalink / raw)
  To: meta-arm; +Cc: nd

> -----Original Message-----
> From: meta-arm@lists.yoctoproject.org <meta-arm@lists.yoctoproject.org>
> On Behalf Of Bertrand Marquis via Lists.Yoctoproject.Org
> Sent: 27 March 2020 10:52
> To: meta-arm@lists.yoctoproject.org
> Cc: nd <nd@arm.com>
> Subject: [meta-arm] [PATCH 1/7] arm-autonomy: Create xenguest-mkimage
> 
> Create a xenguest-mkimage tool to create Xen guest images.
> Add documentation to explain what is a xenguest-image and how to use
> xenguest-mkimage.
> 
> Change-Id: Id87240a4dfac2723f1dcceb8bfe969a7633ef261
> Issue-Id: SCM-767
> Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>

Reviewed-by: Diego Sueiro <diego.sueiro@arm.com>

> ---
>  meta-arm-autonomy/README.md                   |   3 +
>  .../documentation/xenguest-mkimage.md         | 119 +++
>  .../xenguest/files/xenguest-mkimage           | 770 ++++++++++++++++++
>  .../xenguest/xenguest-mkimage.bb              |  31 +
>  4 files changed, 923 insertions(+)
>  create mode 100644 meta-arm-autonomy/documentation/xenguest-
> mkimage.md
>  create mode 100755 meta-arm-autonomy/recipes-
> extended/xenguest/files/xenguest-mkimage
>  create mode 100644 meta-arm-autonomy/recipes-
> extended/xenguest/xenguest-mkimage.bb
> 
> diff --git a/meta-arm-autonomy/README.md b/meta-arm-
> autonomy/README.md index 78a7281..560a783 100644
> --- a/meta-arm-autonomy/README.md
> +++ b/meta-arm-autonomy/README.md
> @@ -67,6 +67,9 @@ This layer is adding the following recipes and classes:
>  * [xen-devicetree](documentation/xen-devicetree.md): this is a recipe to
> modify
>    a device tree blob to add information required to boot xen and a Dom0 linux.
> 
> +* [xenguest-mkimage](documentation/xenguest-mkimage.md): this is a tool
> +to
> +  create and modify images to be used as Xen guests.
> +
>  Contributing
>  ------------
>  This project has not put in place a process for contributions currently. If you
> diff --git a/meta-arm-autonomy/documentation/xenguest-mkimage.md
> b/meta-arm-autonomy/documentation/xenguest-mkimage.md
> new file mode 100644
> index 0000000..d77fd48
> --- /dev/null
> +++ b/meta-arm-autonomy/documentation/xenguest-mkimage.md
> @@ -0,0 +1,119 @@
> +Xenguest mkimage
> +================
> +
> +Introduction
> +------------
> +
> +xenguest-mkimage is a tool to create and modify images to be used as
> +Guest with Xen. It defines a format to store completely defined guests
> +as a file or as a directory and provides options to create and modify those
> images.
> +
> +A xenguest image contains all elements required to create a xen guest.
> +This is the base elements like a Xen configuration and a Linux kernel
> +binary but also some more advanced elements like init scripts or a disk
> definition.
> +
> +The format is made to be deployable easily by storing everything in a
> +single file and provide tools to easily manipulate the images. It can
> +also easily be extended to have features like encryption or signature
> +of images, updates or complex configurations by providing features to
> +have init script that will be executed on the host embedded inside the image.
> +
> +Xenguest images content
> +-----------------------
> +
> +### params.cfg
> +
> +This file contains parameters that can be used by tools to configure
> +some functionalities on the host. This can be used by init scripts to
> +have configurable parameters as it is sourced before calling init scripts.
> +
> +### guest.cfg and guest.d
> +
> +guest.cfg is the main xen configuration and guest.d contains optional
> +configuration parts. All those will be merged into one final xen
> +configuration before starting the guest.
> +
> +### files
> +This directory contains files that can be used by the xen
> +configuration, for example the binary of the kernel referenced in xen
> configuration).
> +This is where the kernel binary, the dtb or a ramdisk will be stored.
> +
> +### init.pre, init.d and init.post
> +These directories contain init scripts that will be executed on the
> +host during the guest startup. Those must be shell scripts and each
> +directory contains scripts called at a different time:
> + - init.pre: scripts executed before the guest is created. This can be used
> +     to prepare some features required to create the guest in xen or to
> +     generate part of the xen configuration dynamically.
> + - init.d: scripts executed when the guest has been created but before it is
> +     started. This can be used to do some xenstore operations or configure the
> +     guest behaviour using xl, for example.
> + - init.post: scripts executed just after starting the guest. This can be
> +     used to configure things created by xen for the guest like network
> +     network interfaces.
> +
> +When a directory contains several scripts, those will be called in
> +alphabetical order.
> +
> +### disk.cfg and disk-files
> +disk.cfg contains the guest disk description (disk size and disk partitions).
> +The file contains the following entries:
> +- `DISK_SIZE=X`: size of the disk to create in GB
> +- `DISK_PARTX=SIZE:FS:CONTENT`: create a partition number X (1 to 4)
> +with a
> +  size of SIZE GB, format it with filesystem FS (can be ext2, ext3,
> +ext4, vfat
> +  or swap) and extract CONTENT as initial partition content
> +  (.tar[.gz|.xz|.bz2] file or img file to be dumped in the partition).
> +FS and
> +  CONTENT can be empty.
> +
> +The disk-files contain files to be used for initializing the disk
> +partitions content. Those should be used to create a LVM or a physical
> +disk and initialize it (create partitions, format them and put the initial content).
> +
> +Usage
> +-----
> +
> +xenguest-mkimage is a shell script which must be called like this:
> +`xenguest-mkimage OPERATION XENGUEST [OPTIONS]`
> +
> +### Operations
> +- create: create a xenguest image. If XENGUEST is an existing empty
> +directory,
> +  the image is created as a directory otherwise it will be created as a file.
> +- check: verify that XENGUEST is a valid xenguest image.
> +- update: modify a xenguest image (see --help for a list of operations).
> +- pack: pack a xenguest image directory into a xenguest image file. The
> +file to
> +  be created must be given as 3rd argument.
> +- extract: extract a xenguest image file into a directory. The
> +destination
> +  directory must be given as 3rd argument.
> +- dump-xenconfig: dump xenguest image xen configuration.
> +- dump-diskconfig: dump xenguest image disk configuration.
> +- dump-paramsconfig: dump xenguest image parameters configuration.
> +
> +For a detailed help on available operations, please use:
> +`xenguest-mkimage --help`
> +
> +### Options
> +- --kernel=FILE: add kernel FILE as guest kernel. This is both adding
> +the file
> +  to the image and modifying the xen configuration to use it.
> +- --xen-memory=SIZE: set the guest memory size in MB.
> +- --xen-extra: add a kernel command line argument. This can be called
> +several
> +  times to add several command line options.
> +- --xen-device-tree=FILE: add dtb FILE as device tree. This both adding
> +the
> +  file to the image and modifying the xen configuration to use it.
> +- --init-script=FILE: add guest init script. The script is embedded
> +inside the
> +  image file. Several script can be added and the basename of FILE is
> +used to
> +  distinguish them (calling the option twice with the same file will
> +update the
> +  script in the image with the second one).
> + --disk-size=SIZE: set the guest disk size to SIZE in GB. Calling this
> +with 0
> +  disable the guest disk.
> +- --disk-add-part=NUM:SIZE:FS:CONTENT: This is adding a partition to
> +the
> +  xenguest image disk. The partition is described with the arguments:
> +  - NUM: partition number.
> +  - SIZE: partition size in GB.
> +  - FS: filesystem to format the partition with. This can be ext2, ext3, ext4,
> +    vfat of swap. If empty the partition is not formated.
> +  - CONTENT: tar of img file to use to initialize the partition. The file must
> +    be added to the image using --disk-add-file=FILE:CONTENT.
> +
> +For a detailed help on available options, please use:
> +`xenguest-mkimage OPERATION --help`
> +
> diff --git a/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-
> mkimage b/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-
> mkimage
> new file mode 100755
> index 0000000..58fcd01
> --- /dev/null
> +++ b/meta-arm-autonomy/recipes-extended/xenguest/files/xenguest-
> mkimage
> @@ -0,0 +1,770 @@
> +#!/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)
> +                         - 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() {
> +    partid=${1}
> +    partsize=${2}
> +    partfs=${3}
> +    partcont=${4:-}
> +
> +    # Make we don't add the same partition twice
> +    disk_config_rm_part ${partid}
> +    echo "DISK_PART${partid}=\"${partsize}:${partfs}:${partcont}\"" >> \
> +        ${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 ./guest.d
> +        else
> +            cat ${guestfile}/guest.cfg ${guestfile}/guest.d/*
> +        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: Cannot pack a xenguest image"
> +            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 config extract"
> +            exit 1
> +        fi
> +
> +        tar -C ${1} -xf ${guestfile}
> +        exit 0
> +        ;;
> +    extract-config)
> +        check_image ${guestfile}
> +        if [ ! -f ${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 [ ! -f ${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 $(echo "${optarg}" | tr ":" " ")
> +            ;;
> +        --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/meta-arm-autonomy/recipes-extended/xenguest/xenguest-
> mkimage.bb b/meta-arm-autonomy/recipes-extended/xenguest/xenguest-
> mkimage.bb
> new file mode 100644
> index 0000000..6ea5fb1
> --- /dev/null
> +++ b/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=0835ade698e0bcf8506ecda2f7b
> 4f302"
> +
> +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"
> +
> --
> 2.17.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [meta-arm] [PATCH 2/7] arm-autonomy: Create xenguest-manager
  2020-03-27 10:52 ` [PATCH 2/7] arm-autonomy: Create xenguest-manager Bertrand Marquis
@ 2020-03-27 15:27   ` Diego Sueiro
  0 siblings, 0 replies; 15+ messages in thread
From: Diego Sueiro @ 2020-03-27 15:27 UTC (permalink / raw)
  To: meta-arm; +Cc: nd

> -----Original Message-----
> From: meta-arm@lists.yoctoproject.org <meta-arm@lists.yoctoproject.org>
> On Behalf Of Bertrand Marquis via Lists.Yoctoproject.Org
> Sent: 27 March 2020 10:52
> To: meta-arm@lists.yoctoproject.org
> Cc: nd <nd@arm.com>
> Subject: [meta-arm] [PATCH 2/7] arm-autonomy: Create xenguest-manager
> 
> Add xenguest-manager to handle xenguest image based guests:
> - create guest (use LVM to create disks for guests)
> - start/stop guests
> - provide init script to have guest auto started on boot
> - add documentation
> 
> Change-Id: I5319ecb77f3aa9f8c1aff4891c05973288156f11
> Issue-Id: SCM-767
> Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>

Reviewed-by: Diego Sueiro <diego.sueiro@arm.com>

> ---
>  meta-arm-autonomy/README.md                   |   4 +
>  .../documentation/xenguest-manager.md         |  67 ++
>  .../images/arm-autonomy-host-image-minimal.bb |   1 +
>  .../xenguest/files/xenguest-init              |  85 +++
>  .../xenguest/files/xenguest-manager           | 640 ++++++++++++++++++
>  .../xenguest/xenguest-manager.bb              |  52 ++
>  .../xenguest/xenguest-manager.bbappend        |   6 +
>  7 files changed, 855 insertions(+)
>  create mode 100644 meta-arm-autonomy/documentation/xenguest-
> manager.md
>  create mode 100755 meta-arm-autonomy/recipes-
> extended/xenguest/files/xenguest-init
>  create mode 100755 meta-arm-autonomy/recipes-
> extended/xenguest/files/xenguest-manager
>  create mode 100644 meta-arm-autonomy/recipes-
> extended/xenguest/xenguest-manager.bb
>  create mode 100644 meta-arm-autonomy/recipes-
> extended/xenguest/xenguest-manager.bbappend
> 
> diff --git a/meta-arm-autonomy/README.md b/meta-arm-
> autonomy/README.md index 560a783..93b5723 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 0000000..387af94
> --- /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 5e09eac..ffe5bce 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-
> mini
> +++ mal.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 0000000..9563d2f
> --- /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 0000000..1daebc1
> --- /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 <<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()
> +{
> +    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
> +
> +            # 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 0000000..9affae9
> --- /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=0835ade698e0bcf8506ecda2f7b
> 4f302"
> +
> +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 0000000..874cfed
> --- /dev/null
> +++ b/meta-arm-autonomy/recipes-extended/xenguest/xenguest-
> manager.bbapp
> +++ end
> @@ -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"
> --
> 2.17.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [meta-arm] [PATCH 3/7] arm-autonomy: Create xenguest-image class
  2020-03-27 10:52 ` [PATCH 3/7] arm-autonomy: Create xenguest-image class Bertrand Marquis
@ 2020-03-27 15:27   ` Diego Sueiro
  0 siblings, 0 replies; 15+ messages in thread
From: Diego Sueiro @ 2020-03-27 15:27 UTC (permalink / raw)
  To: meta-arm; +Cc: nd

> -----Original Message-----
> From: meta-arm@lists.yoctoproject.org <meta-arm@lists.yoctoproject.org>
> On Behalf Of Bertrand Marquis via Lists.Yoctoproject.Org
> Sent: 27 March 2020 10:52
> To: meta-arm@lists.yoctoproject.org
> Cc: nd <nd@arm.com>
> Subject: [meta-arm] [PATCH 3/7] arm-autonomy: Create xenguest-image class
> 
> Create xenguest-image class to be used by recipes and other classes to
> manipulate xenguest images.
> The recipe is defining some variables to configure default parameters of
> xenguest image (memory size, number of vcpus, command line, etc.). Those
> parameters all have the prefix XENGUEST_IMAGE_ and are documented at the
> beginning of the class.
> 
> The class also provide some helper functions:
> - xenguest_image_create to create a xenguest image (using global
> parameters) in deploy as xenguest image directory
> - xenguest_image_clone to clone current xenguest image from deploy to be
> able to extend it and pack it in a xenguest image file
> - xenguest_image_rootfs_file function to allow other recipes to detect if the
> rootfs should or not be embedded in the xenguest image
> 
> Change-Id: I4ba54aa2c41e72964c152f673b71fe32f30b4aca
> Issue-Id: SCM-767
> Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>

Reviewed-by: Diego Sueiro <diego.sueiro@arm.com>

> ---
>  .../classes/xenguest-image.bbclass            | 187 ++++++++++++++++++
>  1 file changed, 187 insertions(+)
>  create mode 100644 meta-arm-autonomy/classes/xenguest-image.bbclass
> 
> diff --git a/meta-arm-autonomy/classes/xenguest-image.bbclass b/meta-arm-
> autonomy/classes/xenguest-image.bbclass
> new file mode 100644
> index 0000000..fecf1ae
> --- /dev/null
> +++ b/meta-arm-autonomy/classes/xenguest-image.bbclass
> @@ -0,0 +1,187 @@
> +# This class must be used to create, extend or pack a xenguest image.
> +# It is using xenguest-mkimage tool to do operations
> +
> +DEPENDS += "xenguest-mkimage-native"
> +
> +#
> +# Xenguest image parameters
> +# All the following parameters can be modified in local.conf or on
> +recipes # inheriting this class #
> +
> +# Guest memory size in MB
> +XENGUEST_IMAGE_MEMORY_SIZE ??= "512"
> +
> +# Guest number of vcpus
> +XENGUEST_IMAGE_NUM_VCPUS ??= "1"
> +
> +# Guest auto boot during init, set to 1 to have guest started during
> +init or # to 0 if the guest should not be auto started
> +XENGUEST_IMAGE_AUTOBOOT ??= "1"
> +
> +# Partition containing the root file system # Xen will actually add
> +root=${XENGUEST_IMAGE_ROOT} to your guest kernel # command line # You
> +can let this empty if the root filesystem is specified in an other way
> +# and have root= option added to the command line for example or if you
> +don't # need a root filesystem mounted for your guest (initrd for
> +example) XENGUEST_IMAGE_ROOT ??= "/dev/xvda1"
> +
> +# Guest kernel command line arguments
> +XENGUEST_IMAGE_CMDLINE ??= "earlyprintk=xenboot console=hvc0 rw"
> +
> +# Extra commands to add to xenguest-image when creating the image
> +XENGUEST_IMAGE_EXTRA_CMD ??= ""
> +
> +# Kernel binary
> +# This value is used by the xenguest image type but is declared here to
> +have # all variables in the same place # Default value is:
> +# - Image if INITRAMFS_IMAGE is not set # -
> +Image-initramfs-${MACHINE}.bin if INITRAMFS_IMAGE is set # If this
> +value is empty no kernel will be added to the image
> +XENGUEST_IMAGE_KERNEL ??= "${@ 'Image' if not
> d.getVar('INITRAMFS_IMAGE') else 'Image-initramfs-${MACHINE}.bin'}"
> +
> +# Size of the disk to create (if 0 no disk will be created and rootfs
> +will not # be included in the xenguest image) XENGUEST_IMAGE_DISK_SIZE
> +??= "${@ '4' if not d.getVar('INITRAMFS_IMAGE') else '0'}"
> +
> +#
> +# XENGUEST_IMAGE_DISK PARTITIONS is used to describe the partitions to
> +setup # and their content.
> +# It must be set to a space separated list of entries with each entry
> +having # the format num:sz:fs:[file] where:
> +# - num is a partition number
> +# - sz is the partition size in Gigabit # - fs is the filesystem to use
> +for the partition # - file is optionally pointing to a file to use as
> +content of the partition
> +#   Please check image_types_xenguest.bbclass for rootfs handling of files
> +#
> +# Default value creates a partition 1 using the full disk, formated
> +with ext4 # and containing the root filesystem produced by Yocto
> +XENGUEST_IMAGE_DISK_PARTITIONS ??=
> "1:${XENGUEST_IMAGE_DISK_SIZE}:ext4:rootfs.tar.gz"
> +
> +# Sub-directory in wich the guest is created. This is create in deploy
> +as a # subdirectory and must be coherent between all components using
> +this class so # it must only be modified from local.conf if needed
> +XENGUEST_IMAGE_DEPLOY_SUBDIR ?= "xenguest"
> +
> +# Directory in which the xenguest should be deployed # a sub-directory
> +named ${XENGUEST_IMAGE_DEPLOY_SUBDIR} will be created there.
> +# This should be set to:
> +# - ${DEPLOYDIR} (default) if creating or extending the xenguest for a normal
> +#   recipe.
> +# - something in ${WORKDIR} if you need to clone and manipulate an
> +image XENGUEST_IMAGE_DEPLOY_DIR ??= "${DEPLOYDIR}"
> +
> +#
> +# Wrapper to call xenguest-mkimage
> +# It is using XENGUEST_IMAGE_DEPLOY_DIR and
> +XENGUEST_IMAGE_DEPLOY_SUBDIR # to find the image to operate on # #
> +Usage: call_xenguest_mkimage [operation] [args]
> +call_xenguest_mkimage() {
> +    local cmd="${1}"
> +    local
> img="${XENGUEST_IMAGE_DEPLOY_DIR}/${XENGUEST_IMAGE_DEPLOY_SUB
> DIR}"
> +    shift
> +
> +    echo "xenguest-mkimage $cmd $img $@"
> +    xenguest-mkimage $cmd $img $@
> +}
> +
> +#
> +# Create an initial xenguest image.
> +# This is a task which must be added in a recipe inheriting deploy # It
> +is using XENGUEST_IMAGE_MEMORY_SIZE,
> XENGUEST_IMAGE_NUM_VCPUS, #
> +XENGUEST_IMAGE_AUTOBOOT, XENGUEST_IMAGE_ROOT,
> XENGUEST_IMAGE_EXTRA_CMD,
> +#  XENGUEST_IMAGE_CMDLINE, XENGUEST_IMAGE_DISK_SIZE and #
> +XENGUEST_IMAGE_DISK_PARTITIONS to customize the initial guest #
> +xenguest_image_create() {
> +    if [ -z "${XENGUEST_IMAGE_DEPLOY_DIR}" -o \
> +        -z "${XENGUEST_IMAGE_DEPLOY_SUBDIR}" ]; then
> +        die "Configuration error: XENGUEST_IMAGE_DEPLOY_DIR or
> XENGUEST_IMAGE_DEPLOY_SUBDIR is empty"
> +    fi
> +
> +    rm -rf
> ${XENGUEST_IMAGE_DEPLOY_DIR}/${XENGUEST_IMAGE_DEPLOY_SUBDIR}
> +
> +    mkdir -p
> + ${XENGUEST_IMAGE_DEPLOY_DIR}/${XENGUEST_IMAGE_DEPLOY_SUBDIR}
> +
> +    # Create the image
> +    call_xenguest_mkimage create --xen-
> memory=${XENGUEST_IMAGE_MEMORY_SIZE} \
> +        --xen-vcpus=${XENGUEST_IMAGE_NUM_VCPUS} \
> +        --xen-root=${XENGUEST_IMAGE_ROOT} \
> +        ${XENGUEST_IMAGE_EXTRA_CMD}
> +
> +    # add command line
> +    if [ -n "${XENGUEST_IMAGE_CMDLINE}" ]; then
> +        call_xenguest_mkimage update --xen-clean-extra
> +        for arg in ${XENGUEST_IMAGE_CMDLINE}; do
> +            call_xenguest_mkimage update --xen-extra=$arg
> +        done
> +    fi
> +
> +    # create disk if needed
> +    disksize="${XENGUEST_IMAGE_DISK_SIZE}"
> +    if [ -z "$disksize" ]; then
> +        disksize="0"
> +    fi
> +    if [ $disksize -gt 0 ]; then
> +        # setup disk size
> +        call_xenguest_mkimage update --disk-reset-config
> + --disk-size=$disksize
> +
> +        diskparts="${XENGUEST_IMAGE_DISK_PARTITIONS}"
> +        if [ -n "$diskparts" ]; then
> +            for arg in $diskparts; do
> +                call_xenguest_mkimage update --disk-add-part=$arg
> +                partnum="$(expr $partnum + 1)"
> +            done
> +        fi
> +    fi
> +
> +    if [ "${XENGUEST_IMAGE_AUTOBOOT}" = "1" ]; then
> +        call_xenguest_mkimage update --set-param=GUEST_AUTOBOOT=1
> +    else
> +        call_xenguest_mkimage update --set-param=GUEST_AUTOBOOT=0
> +    fi
> +}
> +
> +#
> +# Clone the current xenguest from deploy to manipulate it locally #
> +This is required if you need to change things before packing an image #
> +To set the local directory where to clone you must set #
> +XENGUEST_IMAGE_DEPLOY_DIR if you don't want to use do_deploy to
> modify
> +the # image #
> +xenguest_image_clone() {
> +    if [ -z "${XENGUEST_IMAGE_DEPLOY_DIR}" -o \
> +        -z "${XENGUEST_IMAGE_DEPLOY_SUBDIR}" ]; then
> +        die "Configuration error: XENGUEST_IMAGE_DEPLOY_DIR or
> XENGUEST_IMAGE_DEPLOY_SUBDIR is empty"
> +    fi
> +
> +    if [ ! -f
> ${DEPLOY_DIR_IMAGE}/${XENGUEST_IMAGE_DEPLOY_SUBDIR}/guest.cfg ];
> then
> +        die "xenguest-image:
> ${DEPLOY_DIR_IMAGE}/${XENGUEST_IMAGE_DEPLOY_SUBDIR} does not
> contain a valid guest"
> +    fi
> +
> +    rm -rf
> ${XENGUEST_IMAGE_DEPLOY_DIR}/${XENGUEST_IMAGE_DEPLOY_SUBDIR}
> +    mkdir -p ${XENGUEST_IMAGE_DEPLOY_DIR}
> +    cp -rf ${DEPLOY_DIR_IMAGE}/${XENGUEST_IMAGE_DEPLOY_SUBDIR} \
> +
> ${XENGUEST_IMAGE_DEPLOY_DIR}/${XENGUEST_IMAGE_DEPLOY_SUBDIR}
> +}
> +
> +# Helper function to retrieve rootfs file if present in one partition #
> +This can return an empty string or rootfs.tar[.COMP] def
> +xenguest_image_rootfs_file(d):
> +    disksize = d.getVar('XENGUEST_IMAGE_DISK_SIZE')
> +    # if disksize is 0, we don't create anything
> +    if not disksize or disksize == '0':
> +        return ""
> +    # Find first partition with file=rootfs.tar*
> +    partlist = d.getVar('XENGUEST_IMAGE_DISK_PARTITIONS')
> +    if partlist:
> +        for partdesc in partlist.split():
> +            partelems = partdesc.split(':', 3)
> +            if partelems[3]:
> +                if partelems[3].startswith('rootfs.tar'):
> +                    return partelems[3]
> +    return ""
> --
> 2.17.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [meta-arm] [PATCH 4/7] arm-autonomy: Create xenguest-base-image recipe
  2020-03-27 10:52 ` [PATCH 4/7] arm-autonomy: Create xenguest-base-image recipe Bertrand Marquis
@ 2020-03-27 15:28   ` Diego Sueiro
  0 siblings, 0 replies; 15+ messages in thread
From: Diego Sueiro @ 2020-03-27 15:28 UTC (permalink / raw)
  To: meta-arm; +Cc: nd

> -----Original Message-----
> From: meta-arm@lists.yoctoproject.org <meta-arm@lists.yoctoproject.org>
> On Behalf Of Bertrand Marquis via Lists.Yoctoproject.Org
> Sent: 27 March 2020 10:52
> To: meta-arm@lists.yoctoproject.org
> Cc: nd <nd@arm.com>
> Subject: [meta-arm] [PATCH 4/7] arm-autonomy: Create xenguest-base-image
> recipe
> 
> Add xenguest-base-image recipe to create an initial xenguest image directory
> in deploy.
> This is using the xenguest-image class.
> The recipe is also introducing several parameters named
> XENGUEST_IMAGE_SRC_URI_* to allow the user to specify files or elements to
> be added to the xenguest image.
> Those parameters are documented inside the recipe.
> 
> Change-Id: I806a2fa07fb9593c366d88e2f4ee8b649cbcf8ea
> Issue-Id: SCM-767
> Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>

Reviewed-by: Diego Sueiro <diego.sueiro@arm.com>

> ---
>  .../xenguest/xenguest-base-image.bb           | 116 ++++++++++++++++++
>  1 file changed, 116 insertions(+)
>  create mode 100644 meta-arm-autonomy/recipes-
> extended/xenguest/xenguest-base-image.bb
> 
> diff --git a/meta-arm-autonomy/recipes-extended/xenguest/xenguest-base-
> image.bb b/meta-arm-autonomy/recipes-extended/xenguest/xenguest-base-
> image.bb
> new file mode 100644
> index 0000000..ea4a9f3
> --- /dev/null
> +++ b/meta-arm-autonomy/recipes-extended/xenguest/xenguest-base-
> image.bb
> @@ -0,0 +1,116 @@
> +# 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=0835ade698e0bcf8506ecda2f7b
> 4f302"
> +
> +#
> +# 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 you download 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 ??= ""
> +
> +# Add init script
> +
> +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"
> +
> +    if [ -d ${WORKDIR}/extend/$subdir ]; then
> +        filelist=$(find ${WORKDIR}/extend/$subdir -type f)
> +
> +        if [ -n "$filelist" ]; then
> +            for f in $filelist; do
> +                call_xenguest_mkimage update --$cmd=$f:$(basename $f)
> +            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"
> +    add_extend_files "files" "xen-add-file"
> +    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
> +
> --
> 2.17.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [meta-arm] [PATCH 5/7] arm-autonomy: Create xenguest image type
  2020-03-27 10:52 ` [PATCH 5/7] arm-autonomy: Create xenguest image type Bertrand Marquis
@ 2020-03-27 15:28   ` Diego Sueiro
  0 siblings, 0 replies; 15+ messages in thread
From: Diego Sueiro @ 2020-03-27 15:28 UTC (permalink / raw)
  To: meta-arm; +Cc: nd

> -----Original Message-----
> From: meta-arm@lists.yoctoproject.org <meta-arm@lists.yoctoproject.org>
> On Behalf Of Bertrand Marquis via Lists.Yoctoproject.Org
> Sent: 27 March 2020 10:52
> To: meta-arm@lists.yoctoproject.org
> Cc: nd <nd@arm.com>
> Subject: [meta-arm] [PATCH 5/7] arm-autonomy: Create xenguest image type
> 
> Create an image type xenguest to create a xenguest image as part of a Yocto
> image (add FSTYPE xenguest).
> 
> The image type is using xenguest-base-image as a producer for the xenguest
> image directory, adds kernel defined by XENGUEST_IMAGE_KERNEL to it, adds
> rootfs if listed in XENGUEST_IMAGE_DISK_PARTITIONS and pack the final
> image with file extension .xenguest with other types of images.
> 
> If initramfs is configured, a xenguest image containing the kernel with initramfs
> is produced.
> 
> The xenguest image type is added to IMAGE_FSTYPES and IMAGE_CLASSES if
> arm-autonomy-guest is set in DISTRO_FEATURES.
> 
> Change-Id: Ibae8a50d41375839492e43a2e28d9472dc71b4a1
> Issue-Id: SCM-767
> Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>

Reviewed-by: Diego Sueiro <diego.sueiro@arm.com>

> ---
>  .../classes/image_types_xenguest.bbclass      | 132 ++++++++++++++++++
>  .../distro/include/arm-autonomy-guest.inc     |   4 +
>  2 files changed, 136 insertions(+)
>  create mode 100644 meta-arm-
> autonomy/classes/image_types_xenguest.bbclass
> 
> diff --git a/meta-arm-autonomy/classes/image_types_xenguest.bbclass
> b/meta-arm-autonomy/classes/image_types_xenguest.bbclass
> new file mode 100644
> index 0000000..ff1e41a
> --- /dev/null
> +++ b/meta-arm-autonomy/classes/image_types_xenguest.bbclass
> @@ -0,0 +1,132 @@
> +# Create a xenguest image with kernel and filesystem produced by Yocto
> +# This will create a .xenguest file that the xenguest-manager can use.
> +
> +inherit xenguest-image deploy
> +
> +# We are creating our guest in a local subdirectory # force the value
> +so that we are not impacted if the user is changing it
> +XENGUEST_IMAGE_DEPLOY_DIR = "${WORKDIR}/tmp-xenguest"
> +
> +# Name of deployed file (keep standard image name and add .xenguest)
> +XENGUEST_IMAGE_DEPLOY ??= "${IMAGE_NAME}"
> +
> +# Deployed file when building with initramfs
> +XENGUEST_IMAGE_INITRAMFS_DEPLOY ??= "Image-initramfs-${MACHINE}"
> +
> +# Add kernel XENGUEST_IMAGE_KERNEL from DEPLOY_DIR_IMAGE to image
> +xenguest_image_add_kernel() {
> +    srcfile="${1:-}"
> +    if [ -z "${srcfile}" ]; then
> +        srcfile="${DEPLOY_DIR_IMAGE}/${XENGUEST_IMAGE_KERNEL}"
> +    fi
> +    call_xenguest_mkimage partial --xen-kernel=$srcfile }
> +
> +# Add rootfs file to the image
> +xenguest_image_add_rootfs() {
> +    call_xenguest_mkimage partial \
> +
> +--disk-add-
> file=${IMGDEPLOYDIR}/${IMAGE_LINK_NAME}.${IMAGE_TYPEDEP_xeng
> +uest}:rootfs.${IMAGE_TYPEDEP_xenguest}
> +}
> +
> +# Pack xenguest image
> +xenguest_image_pack() {
> +    mkdir -p ${IMGDEPLOYDIR}
> +    rm -f ${IMGDEPLOYDIR}/${XENGUEST_IMAGE_DEPLOY}.xenguest
> +    call_xenguest_mkimage pack \
> +        ${IMGDEPLOYDIR}/${XENGUEST_IMAGE_DEPLOY}.xenguest
> +}
> +
> +# do_deploy is used for initramfs to pack the kernel initramfs in an
> +image
> +do_deploy() {
> +    # Add kernel
> +    xenguest_image_add_kernel
> +
> +    # Pack the image in deploydir
> +    mkdir -p ${DEPLOYDIR}
> +    rm -f ${DEPLOYDIR}/${XENGUEST_IMAGE_INITRAMFS_DEPLOY}.xenguest
> +    call_xenguest_mkimage pack \
> +        ${DEPLOYDIR}/${XENGUEST_IMAGE_INITRAMFS_DEPLOY}.xenguest
> +}
> +do_deploy[depends] += "${PN}:do_bootimg_xenguest"
> +do_deploy[depends] += "virtual/kernel:do_deploy"
> +
> +#
> +# Task finishing the bootimg
> +# We need this task to actually create the symlinks # python
> +do_bootimg_xenguest() {
> +    subtasks = d.getVarFlag('do_bootimg_xenguest', 'subtasks')
> +
> +    bb.build.exec_func('xenguest_image_clone', d)
> +    if subtasks:
> +        for tk in subtasks.split():
> +            bb.build.exec_func(tk, d)
> +    bb.build.exec_func('xenguest_image_pack', d)
> +    bb.build.exec_func('create_symlinks', d) } # This is used to add
> +sub-tasks to do_bootimg_xenguest do_bootimg_xenguest[subtasks] = ""
> +# Those are required by create_symlinks to find our image
> +do_bootimg_xenguest[subimages] = "xenguest"
> +do_bootimg_xenguest[imgsuffix] = "."
> +do_bootimg_xenguest[depends] += "xenguest-base-image:do_deploy"
> +# Need to have rootfs so all recipes have deployed their content
> +do_bootimg_xenguest[depends] += "${PN}:do_rootfs"
> +
> +# This set in python anonymous after, just set a default value here
> +IMAGE_TYPEDEP_xenguest ?= "tar"
> +
> +# We must not be built at rootfs build time because we need the kernel
> +IMAGE_TYPES_MASKED += "xenguest"
> +IMAGE_TYPES += "xenguest"
> +
> +python __anonymous() {
> +    # Do not do anything if we are not in the want FSTYPES
> +    if bb.utils.contains_any('IMAGE_FSTYPES', 'xenguest', '1', '0', d):
> +
> +        # Check the coherency of the configuration
> +        rootfs_needed = False
> +        rootfs_file = ''
> +        kernel_needed = False
> +        initramfs_needed = False
> +
> +        rootfs_file = xenguest_image_rootfs_file(d)
> +        if rootfs_file:
> +            rootfs_needed = True
> +
> +        if d.getVar('XENGUEST_IMAGE_KERNEL'):
> +            kernel_needed = True
> +
> +        if d.getVar('INITRAMFS_IMAGE'):
> +            if int(d.getVar('INITRAMFS_IMAGE_BUNDLE')) != 1:
> +                bb.error("xenguest-fstype: INITRAMFS_IMAGE is set but
> INITRAMFS_IMAGE_BUNDLE is set to 0.\n")
> +                bb.fatal("xenguest-fstype: This configuration is not supported by
> xenguest image type\n")
> +            initramfs_needed = True
> +
> +        if initramfs_needed and rootfs_needed:
> +            bb.warn("xenguest-fstype: Final image will use an initramfs kernel and
> rootfs in disk.\n")
> +            bb.warn("xenguest-fstype: rootfs.tar.%s should be removed
> + from XENGUEST_IMAGE_DISK_PARTITIONS.\n")
> +
> +        if not initramfs_needed and not rootfs_needed and not kernel_needed:
> +            bb.warn("xenguest-fstype: Generated image will have no
> + kernel and no rootfs.\n")
> +
> +        bb.build.addtask('do_bootimg_xenguest', 'do_image_complete',
> + None, d)
> +
> +        if rootfs_needed:
> +            # tell do_bootimg_xenguest to call add_rootfs
> +            d.appendVarFlag('do_bootimg_xenguest', 'subtasks', '
> xenguest_image_add_rootfs')
> +            # do_bootimg_xenguest will need the tar file
> +            d.appendVarFlag('do_bootimg_xenguest', 'depends',
> ' %s:do_image_tar' % (d.getVar('PN')))
> +            # set our TYPEDEP to the proper compression
> +            d.setVar('IMAGE_TYPEDEP_xenguest', 'tar' +
> + (rootfs_file.split('.tar', 1)[1] or ''))
> +
> +        if kernel_needed:
> +            if initramfs_needed:
> +                bb.build.addtask('do_deploy', 'do_build', None, d)
> +            else:
> +                # Tell do_bootimg_xenguest to call xenguest_image_add_kernel
> +                d.appendVarFlag('do_bootimg_xenguest', 'subtasks', '
> xenguest_image_add_kernel')
> +                # we will need kernel do_deploy
> +                d.appendVarFlag('do_bootimg_xenguest', 'depends', '
> +virtual/kernel:do_deploy') }
> +
> diff --git a/meta-arm-autonomy/conf/distro/include/arm-autonomy-guest.inc
> b/meta-arm-autonomy/conf/distro/include/arm-autonomy-guest.inc
> index d961b40..9b5889e 100644
> --- a/meta-arm-autonomy/conf/distro/include/arm-autonomy-guest.inc
> +++ b/meta-arm-autonomy/conf/distro/include/arm-autonomy-guest.inc
> @@ -3,3 +3,7 @@
>  # We need to have ipv4 activated
>  DISTRO_FEATURES_append = " ipv4"
> 
> +# Build a xenguest type image
> +IMAGE_CLASSES += "image_types_xenguest"
> +IMAGE_FSTYPES += "xenguest"
> +
> --
> 2.17.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [meta-arm] [PATCH 6/7] arm-autonomy: Create xenguest-image-extra class
  2020-03-27 10:52 ` [PATCH 6/7] arm-autonomy: Create xenguest-image-extra class Bertrand Marquis
@ 2020-03-27 15:28   ` Diego Sueiro
  0 siblings, 0 replies; 15+ messages in thread
From: Diego Sueiro @ 2020-03-27 15:28 UTC (permalink / raw)
  To: meta-arm; +Cc: nd

> -----Original Message-----
> From: meta-arm@lists.yoctoproject.org <meta-arm@lists.yoctoproject.org>
> On Behalf Of Bertrand Marquis via Lists.Yoctoproject.Org
> Sent: 27 March 2020 10:52
> To: meta-arm@lists.yoctoproject.org
> Cc: nd <nd@arm.com>
> Subject: [meta-arm] [PATCH 6/7] arm-autonomy: Create xenguest-image-extra
> class
> 
> Add class xenguest-image-extra to be used by recipes which wants to add
> elements to the generated xenguest image.
> The recipes using this call must inherit the deploy class and declare a deploy
> task that will be extended by the class. The variables
> XENGUEST_EXTRA_* documented in the class can be used to define what
> should be used to extend the xenguest image.
> 
> Change-Id: I8a7682a7a7ca57b424ea815145408ccb8e4348ca
> Issue-Id: SCM-767
> Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>

Reviewed-by: Diego Sueiro <diego.sueiro@arm.com>

> ---
>  .../classes/xenguest-image-extra.bbclass      | 102 ++++++++++++++++++
>  1 file changed, 102 insertions(+)
>  create mode 100644 meta-arm-autonomy/classes/xenguest-image-
> extra.bbclass
> 
> diff --git a/meta-arm-autonomy/classes/xenguest-image-extra.bbclass
> b/meta-arm-autonomy/classes/xenguest-image-extra.bbclass
> new file mode 100644
> index 0000000..a5697e5
> --- /dev/null
> +++ b/meta-arm-autonomy/classes/xenguest-image-extra.bbclass
> @@ -0,0 +1,102 @@
> +# This class must be used to extend the xenguest image # It provides
> +variables to add init scripts, a dtb, xen files or disk files.
> +#
> +# The class is extending deploy function so you recipe must inherit
> +deploy and # have a do_deploy function (even if it is empty)
> +
> +# Use standard xenguest-image
> +inherit xenguest-image
> +
> +# Add a DTB file for the guest
> +# Only one file should be added, if this is set multiple times or in
> +several # recipes, the last recipe setting it will prevail.
> +XENGUEST_EXTRA_DTB ??= ""
> +
> +# Append something to the guest xen configuration # All files here will
> +be merged together in the final xen configuration # This can contain
> +several files or be used in several recipes XENGUEST_EXTRA_XENCONFIG
> +??= ""
> +
> +# Add a xenguest init, init-pre or init-post script
> +XENGUEST_EXTRA_INIT_PRE ??= ""
> +XENGUEST_EXTRA_INIT ??= ""
> +XENGUEST_EXTRA_INIT_POST ??= ""
> +
> +# Add xenguest files, (to be used in extra xen config for example) #
> +several files may be added, space separated, the path will be kept on
> +the # generated xenguest image (if dir1/file1 is added, it can be used
> +as # dir1/file1 file in the xen configuration).
> +XENGUEST_EXTRA_FILES ??= ""
> +
> +# Add xenguest disk files (to be used as disk partition content) #
> +several files may be added, space separated, the path will be kept on
> +the # generated xenguest image (if dir1/file1 is added, it can be used
> +as # dir1/file1 file in the disk content parameters).
> +XENGUEST_EXTRA_DISK_FILES ??= ""
> +
> +do_deploy_append() {
> +    if [ -z "${XENGUEST_IMAGE_DEPLOY_DIR}" -o \
> +        -z "${XENGUEST_IMAGE_DEPLOY_SUBDIR}" ]; then
> +        die "Configuration error: XENGUEST_IMAGE_DEPLOY_DIR or
> XENGUEST_IMAGE_DEPLOY_SUBDIR is empty"
> +    fi
> +    rm -rf
> ${XENGUEST_IMAGE_DEPLOY_DIR}/${XENGUEST_IMAGE_DEPLOY_SUBDIR}
> +    mkdir -p
> +${XENGUEST_IMAGE_DEPLOY_DIR}/${XENGUEST_IMAGE_DEPLOY_SUBDIR}
> +
> +    if [ -n "${XENGUEST_EXTRA_DTB}" ]; then
> +        if [ ! -f ${XENGUEST_EXTRA_DTB} ]; then
> +            die "xenguest-image: DTB file ${XENGUEST_EXTRA_DTB} does not
> exist"
> +        fi
> +        call_xenguest_mkimage partial --xen-device-
> tree=${XENGUEST_EXTRA_DTB}
> +    fi
> +
> +    if [ -n "${XENGUEST_EXTRA_XENCONFIG}" ]; then
> +        for f in ${XENGUEST_EXTRA_XENCONFIG}; do
> +            if [ ! -f $f ]; then
> +                die "xenguest-image: Xen config $f does not exist"
> +            fi
> +            call_xenguest_mkimage partial --xen-append=$f
> +        done
> +    fi
> +
> +    if [ -n "${XENGUEST_EXTRA_INIT_PRE}" ]; then
> +        if [ ! -f ${XENGUEST_EXTRA_INIT_PRE} ]; then
> +            die "xenguest-image: Init script ${XENGUEST_EXTRA_INIT_PRE} does
> not exist"
> +        fi
> +        call_xenguest_mkimage partial --init-pre=${XENGUEST_EXTRA_INIT_PRE}
> +    fi
> +
> +    if [ -n "${XENGUEST_EXTRA_INIT}" ]; then
> +        if [ ! -f ${XENGUEST_EXTRA_INIT} ]; then
> +            die "xenguest-image: Init script ${XENGUEST_EXTRA_INIT} does not
> exist"
> +        fi
> +        call_xenguest_mkimage partial --init-script=${XENGUEST_EXTRA_INIT}
> +    fi
> +
> +    if [ -n "${XENGUEST_EXTRA_INIT_POST}" ]; then
> +        if [ ! -f ${XENGUEST_EXTRA_INIT_POST} ]; then
> +            die "xenguest-image: Init script ${XENGUEST_EXTRA_INIT_POST} does
> not exist"
> +        fi
> +        call_xenguest_mkimage partial --init-
> post=${XENGUEST_EXTRA_INIT_POST}
> +    fi
> +
> +    if [ -n "${XENGUEST_EXTRA_FILES}" ]; then
> +        for f in ${XENGUEST_EXTRA_FILES}; do
> +            if [ ! -f $f ]; then
> +                die "xenguest-image: Xen file $file does not exist"
> +            fi
> +            call_xenguest_mkimage partial --disk-add-file=$file
> +        done
> +    fi
> +
> +    if [ -n "${XENGUEST_EXTRA_DISK_FILES}" ]; then
> +        for f in ${XENGUEST_EXTRA_DISK_FILES}; do
> +            if [ ! -f $f ]; then
> +                die "xenguest-image: Disk file $f does not exist"
> +            fi
> +            call_xenguest_mkimage partial --disk-add-file=$f
> +        done
> +    fi
> +}
> +# Need to have xenguest-image tool
> +do_deploy[depends] += "xenguest-base-image:do_deploy"
> +
> --
> 2.17.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [meta-arm] [PATCH 7/7] arm-autonomy: Create xenguest-nodisk-image recipe
  2020-03-27 10:52 ` [PATCH 7/7] arm-autonomy: Create xenguest-nodisk-image recipe Bertrand Marquis
@ 2020-03-27 15:29   ` Diego Sueiro
  0 siblings, 0 replies; 15+ messages in thread
From: Diego Sueiro @ 2020-03-27 15:29 UTC (permalink / raw)
  To: meta-arm; +Cc: nd

> -----Original Message-----
> From: meta-arm@lists.yoctoproject.org <meta-arm@lists.yoctoproject.org>
> On Behalf Of Bertrand Marquis via Lists.Yoctoproject.Org
> Sent: 27 March 2020 10:52
> To: meta-arm@lists.yoctoproject.org
> Cc: nd <nd@arm.com>
> Subject: [meta-arm] [PATCH 7/7] arm-autonomy: Create xenguest-nodisk-
> image recipe
> 
> Create a xenguest-nodisk-image recipe to be used when wanting to create a
> xenguest image without packing in it a root filesystem generated by Yocto.
> This recipe can be used to use aio root filesystem from an external tar file and
> just compile and take the linux kernel coming from Yocto.
> 
> To achieve this, the variable XENGUEST_IMAGE_SRC_URI_DISK_FILES should
> be set to a SRC_URI compatible URL to the tar file and then call bitbake
> xenguest-nodisk-image.
> 
> Change-Id: I1a8d80b89930f3bb6bcce40a55b4dfce9b5331ef
> Issue-Id: SCM-767
> Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>

Reviewed-by: Diego Sueiro <diego.sueiro@arm.com>

> ---
>  .../xenguest/xenguest-nodisk-image.bb         | 38 +++++++++++++++++++
>  1 file changed, 38 insertions(+)
>  create mode 100644 meta-arm-autonomy/recipes-
> extended/xenguest/xenguest-nodisk-image.bb
> 
> diff --git a/meta-arm-autonomy/recipes-extended/xenguest/xenguest-nodisk-
> image.bb b/meta-arm-autonomy/recipes-extended/xenguest/xenguest-
> nodisk-image.bb
> new file mode 100644
> index 0000000..b2dbbe9
> --- /dev/null
> +++ b/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=0835ade698e0bcf8506ecda2f7b
> 4f302"
> +
> +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
> +
> --
> 2.17.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2020-03-27 15:29 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-27 10:52 [PATCH 0/7] arm-autonomy: Introduce Xenguest system Bertrand Marquis
2020-03-27 10:52 ` [PATCH 1/7] arm-autonomy: Create xenguest-mkimage Bertrand Marquis
2020-03-27 15:26   ` [meta-arm] " Diego Sueiro
2020-03-27 10:52 ` [PATCH 2/7] arm-autonomy: Create xenguest-manager Bertrand Marquis
2020-03-27 15:27   ` [meta-arm] " Diego Sueiro
2020-03-27 10:52 ` [PATCH 3/7] arm-autonomy: Create xenguest-image class Bertrand Marquis
2020-03-27 15:27   ` [meta-arm] " Diego Sueiro
2020-03-27 10:52 ` [PATCH 4/7] arm-autonomy: Create xenguest-base-image recipe Bertrand Marquis
2020-03-27 15:28   ` [meta-arm] " Diego Sueiro
2020-03-27 10:52 ` [PATCH 5/7] arm-autonomy: Create xenguest image type Bertrand Marquis
2020-03-27 15:28   ` [meta-arm] " Diego Sueiro
2020-03-27 10:52 ` [PATCH 6/7] arm-autonomy: Create xenguest-image-extra class Bertrand Marquis
2020-03-27 15:28   ` [meta-arm] " Diego Sueiro
2020-03-27 10:52 ` [PATCH 7/7] arm-autonomy: Create xenguest-nodisk-image recipe Bertrand Marquis
2020-03-27 15:29   ` [meta-arm] " Diego Sueiro

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.