__dest=/
__pb_mount_dir=/var/petitboot/mnt/dev/
-__plugin_basedir=/tmp/
-plugin_file=pb-plugin.cpio.gz
+plugin_ext=pb-plugin
plugin_meta=pb-plugin.conf
plugin_meta_dir=etc/preboot-plugins/
plugin_meta_path=$plugin_meta_dir$plugin_meta
+plugin_wrapper_dir=/var/lib/pb-plugins/bin
usage()
{
Usage: $0 <command>
Where <command> is one of:
- run <FILE|URL> - run plugin from FILE/URL
- scan - look for available plugins on attached devices
- create <DIR> - create a new plugin archive from DIR
+ install <FILE|URL> - install plugin from FILE/URL
+ scan - look for available plugins on attached devices
+ create <DIR> - create a new plugin archive from DIR
EOF
}
echo " (version $PLUGIN_VERSION)"
}
-__run_init()
+do_wrap()
{
- local base dir
+ local base binary dir
base=$1
+ binary=$2
+ shift 2
- for dir in etc dev sys proc
+ for dir in etc dev sys proc var
do
- mkdir -p $base/$dir
+ [ -e "$base/$dir" ] || mkdir -p "$base/$dir"
done
cp /etc/resolv.conf $base/etc
mount -o bind /dev $base/dev
mount -o bind /sys $base/sys
mount -o bind /proc $base/proc
+ mount -o bind /var $base/var
+
+ chroot "$base" "$binary" "$@"
+
+ umount $base/dev
+ umount $base/sys
+ umount $base/proc
+ umount $base/var
}
-__run_cleanup()
+__create_wrapper()
{
- local base
+ local base binary wrapper
base=$1
+ binary=$2
+ wrapper=$plugin_wrapper_dir/$(basename $binary)
+
+ mkdir -p $plugin_wrapper_dir
+
+ cat <<EOF > $wrapper
+#!/bin/sh
+
+exec $(realpath $0) __wrap '$base' '$binary' "\$@"
+EOF
- [ -e $base/dev/null ] && umount $base/dev
- [ -e $base/sys/kernel ] && umount $base/sys
- [ -e $base/proc/stat ] && umount $base/proc
- rm -rf $base
+ chmod a+x $wrapper
}
-do_run()
+do_install()
{
- local url executable
+ local url name file __dest
url=$1
- executable=$2
if [ -z "$url" ]
then
echo
sha256sum "$file" | cut -f1 -d' '
echo
- echo "Do you want to run this plugin? (y/N)"
+ echo "Do you want to install this plugin? (y/N)"
read resp
case $resp in
. $__dest/$plugin_meta_path
- (
- executable=${PLUGIN_EXECUTABLE:-$executable}
-
- __run_init $__dest
-
- printf "Entering plugin\n"
- plugin_info
-
- chroot $__dest $executable
-
- printf "\nExiting plugin & cleaning up\n"
- __run_cleanup $__dest
- )
+ for binary in ${PLUGIN_EXECUTABLES}
+ do
+ __create_wrapper "$__dest" "$binary"
+ done
+ echo "Plugin installed"
+ plugin_info
}
-do_scan()
+do_scan_mount()
{
- local found dev plugin_path __meta_tmp
- found=0
- for mnt in $__pb_mount_dir/*
- do
- dev=$(basename $mnt)
- plugin_path="$mnt/$plugin_file"
+ local mnt dev plugin_path __meta_tmp
+ mnt=$1
+ dev=$(basename $mnt)
+ for plugin_path in $mnt/*.$plugin_ext
+ do
[ -e "$plugin_path" ] || continue
# extract plugin metadata to a temporary directory
__meta_tmp=$(mktemp -d)
[ -d $__meta_tmp ] || continue
- gunzip -c "$plugin_path" |
+ gunzip -c "$plugin_path" 2>/dev/null |
(cd $__meta_tmp &&
cpio -i -d $plugin_meta_path 2>/dev/null)
if ! [ $? = 0 -a -e "$plugin_path" ]
rm -rf $__meta_tmp
found=1
done
+}
+
+do_scan()
+{
+ local found mnt
+ found=0
+ for mnt in $__pb_mount_dir/*
+ do
+ do_scan_mount $mnt
+ done
if [ "$found" = 0 ]
then
cat <<EOF
-Enter the full path (within the plugin root) to the plugin executable file.
-This will be the default action when the plugin is run. (eg /usr/bin/my-util)
+Enter the full path (within the plugin root) to the plugin executable file(s).
+These will be exposed as wrapper scripts, to be run from the standard petitboot
+shell environment (eg, /usr/bin/my-raid-config).
+
+If multiple executables are provided, separate with a space.
EOF
- read executable
+ read executables
date=$(date +%Y-%m-%d)
cat <<EOF > $file
PLUGIN_VENDOR='$vendorname'
+PLUGIN_VENDOR_ID='$vendorshortname'
PLUGIN_NAME='$pluginname'
+PLUGIN_ID='$pluginshortname'
PLUGIN_VERSION='$version'
PLUGIN_DATE='$date'
-PLUGIN_EXECUTABLE='$executable'
+PLUGIN_EXECUTABLES='$executables'
EOF
}
fi
# Sanity check metadata file
- (
- . $meta_file
- if [ ! -n "$PLUGIN_VENDOR" ]
- then
- echo "error: no PLUGIN_VENDOR defined in metadata" &>2
- exit 1
- fi
- if [ ! -n "$PLUGIN_NAME" ]
- then
- echo "error: no PLUGIN_NAME defined in metadata" &>2
- exit 1
- fi
- if [ ! -n "$PLUGIN_VERSION" ]
- then
- echo "error: no PLUGIN_VERSION defined in metadata" &>2
- exit 1
- fi
- if [ ! -n "$PLUGIN_DATE" ]
- then
- echo "error: no PLUGIN_DATE defined in metadata" &>2
- exit 1
- fi
- if [ ! -n "$PLUGIN_EXECUTABLE" ]
- then
- echo "error: no PLUGIN_EXECUTABLE defined in metadata" \
- &>2
- exit 1
- fi
-
- ) || exit 1
+ . $meta_file
+ if [ ! -n "$PLUGIN_VENDOR" ]
+ then
+ echo "error: no PLUGIN_VENDOR defined in metadata" &>2
+ exit 1
+ fi
+ if [ ! -n "$PLUGIN_VENDOR_ID" ]
+ then
+ echo "error: no PLUGIN_VENDOR_ID defined in metadata" &>2
+ exit 1
+ fi
+ if [ ! -n "$PLUGIN_NAME" ]
+ then
+ echo "error: no PLUGIN_NAME defined in metadata" &>2
+ exit 1
+ fi
+ if [ ! -n "$PLUGIN_ID" ]
+ then
+ echo "error: no PLUGIN_ID defined in metadata" &>2
+ exit 1
+ fi
+ if [ ! -n "$PLUGIN_VERSION" ]
+ then
+ echo "error: no PLUGIN_VERSION defined in metadata" &>2
+ exit 1
+ fi
+ if [ ! -n "$PLUGIN_DATE" ]
+ then
+ echo "error: no PLUGIN_DATE defined in metadata" &>2
+ exit 1
+ fi
+ if [ ! -n "$PLUGIN_EXECUTABLES" ]
+ then
+ echo "error: no PLUGIN_EXECUTABLES defined in metadata" &>2
+ exit 1
+ fi
- outfile=$plugin_file
+ outfile=${PLUGIN_ID}-${PLUGIN_VERSION}.${plugin_ext}
(
cd $src
echo
echo "User-visible metadata:"
-
- (
- . $meta_file
- plugin_info | sed -e 's/^/ /'
- )
+ plugin_info | sed -e 's/^/ /'
echo
-
cat <<EOF
Plugin created in:
$outfile
Ship this file in the top-level-directory of a USB device or CD to have it
-automatically discoverable by 'pb-plugin scan'.
+automatically discoverable by 'pb-plugin scan'. This file can be re-named,
+but must retain the .$plugin_ext extension to be discoverable.
EOF
}
(
echo "PLUGIN_NAME=test"
echo "PLUGIN_VERSION=1"
- echo "PLUGIN_EXECUTABLE=/bin/sh"
+ echo "PLUGIN_EXECUTABLES=/bin/sh"
) > $mnt_dir/$plugin_meta_path
(
cd $mnt_dir;
find -mindepth 1 | cpio -o -Hnewc 2>/dev/null
- ) | gzip -c > $mnt_dir/$plugin_file
+ ) | gzip -c > $mnt_dir/test.$plugin_ext
+
+ do_scan | grep -q 'test'
+}
+
+test_scan_nogzip()
+{
+ __pb_mount_dir="$test_tmpdir/mnt"
+ mnt_dir="$__pb_mount_dir/sda"
+ stderr_file="$test_tmpdir/stderr"
+
+ mkdir -p $mnt_dir
+ echo "invalid" > $mnt_dir/nogzip.$plugin_ext
+
+ do_scan 2>$stderr_file | grep -q 'No plugins'
+
+ [ $? = 0 ] || return 1
+
+ if [ -s "$stderr_file" ]
+ then
+ echo "Scan with invalid (non-gzip) file produced error output" \
+ >&2
+ cat "$stderr_file"
+ return 1
+ fi
+ true
+}
+
+test_scan_nocpio()
+{
+ __pb_mount_dir="$test_tmpdir/mnt"
+ mnt_dir="$__pb_mount_dir/sda"
+ stderr_file="$test_tmpdir/stderr"
+
+ mkdir -p $mnt_dir
+ echo "invalid" | gzip -c > $mnt_dir/nogzip.$plugin_ext
+
+ do_scan 2>$stderr_file | grep -q 'No plugins'
- do_scan | grep -q 'test 1'
- rc=$?
+ [ $? = 0 ] || return 1
+
+ if [ -s "$stderr_file" ]
+ then
+ echo "Scan with invalid (non-cpio) file produced error output" \
+ >&2
+ cat "$stderr_file"
+ return 1
+ fi
+ true
+}
+
+test_scan_multiple()
+{
+ __pb_mount_dir="$test_tmpdir/mnt"
+ mnt_dir="$__pb_mount_dir/sda"
+ outfile=$test_tmpdir/scan.out
+
+ for i in 1 2
+ do
+ mkdir -p $mnt_dir/$plugin_meta_dir
+ (
+ echo "PLUGIN_NAME=test-$i"
+ echo "PLUGIN_VERSION=1"
+ echo "PLUGIN_EXECUTABLES=/bin/sh"
+ ) > $mnt_dir/$plugin_meta_path
+ (
+ cd $mnt_dir;
+ find -mindepth 1 | cpio -o -Hnewc 2>/dev/null
+ ) | gzip -c > $mnt_dir/test-${i}.$plugin_ext
+ rm -rf $mnt_dir/$plugin_meta_dir
+ done
+
+ do_scan >$outfile
+
+ grep -q 'test-1' $outfile && grep -q 'test-2' $outfile
}
test_empty_scan()
do_test test_http_download
do_test test_ftp_download
do_test test_scan
+ do_test test_scan_nogzip
+ do_test test_scan_nocpio
+ do_test test_scan_multiple
do_test test_empty_scan
if [ $test_failed = 0 ]
echo "$n tests passed"
else
echo "Tests failed"
- false
fi
rm -rf "$tests_tmpdir"
+
+ [ $test_failed = 0 ]
}
case "$1" in
-run)
+install)
shift
- do_run $@
+ do_install $@
;;
scan)
shift
shift
do_create $@
;;
+__wrap)
+ shift
+ do_wrap $@
+ ;;
__test)
shift
do_tests $@