vkernel manager
Aggelos Economopoulos
aoiko at cc.ece.ntua.gr
Fri Feb 8 23:07:36 PST 2008
Working with vkernels involves a lot of vnconfig, mount, installworld etc
commands and there's always the posibility that you'll try to write to
a filesystem that is in use by a running vkernel. Some months ago I was
using a set of scripts to help with managing vkernel instances and
diskimages. I took some time to convert them to a single script and expand
them a bit (probably adding some bugs in the process). I suppose other
people have their own scripts; if so, please share them.
You use the script like this:
vkernmgr init -m /mnt/vkern -s 1024 -w /usr/src -k /path/to/vkernel test
[creates and formats an 1G disk image, installs base system from /usr/src]
vkernmgr run test [extra vkernel flags, if any]
[ensures no vn device is configured for access to the diskimage, runs
vkernel]
vkernmgr iw test
[ensures no vkernel is using the diskimage, installs world from /usr/src]
vkernmgr {start,stop}vn test
vkernmgr {,u}mount test
vkernmgr halt test
vkernmgr kill test
[These do the obvious; stopvn may need to run umount, mount may need to run
startvn]
Hopefully this will be useful to someone.
#!/bin/sh
# FIXME: vndev busy on newfs sometimes? Then stuck for good, too.
# FIXME: need better error checking
# FIXME: awk will break on paths with spaces
# TODO: ensure no other configuration that has the same disk image is running
# in startvn, run
# TODO: pass on args to vkernel
# TODO: network setup
loadconf()
{
vkernrc=default
if ! test -z $1 ; then
vkernrc=$1
fi
name="$vkernrc"
. ~/.vkernels/$vkernrc
}
usage()
{
echo "usage:"
exit 2
}
is_running()
{
if test ! -f "/var/run/vkernel_${name}.pid"; then
return 1
fi
pid=`cat /var/run/vkernel_${name}.pid`
kill -0 "$pid"
if test "$?" -ne "0"; then
echo "warning: stale pid file /var/run/vkernel_${name}.pid"
return 1
fi
return 0
}
getvn()
{
awkcmd=`printf '/covering .* on .*$/ { if ($3 == \"%s\") print substr($1, 1, length($1) - 1)}' $diskimage`
vndev=`vnconfig -l | awk "$awkcmd"`
}
cmd_stopvn()
{
getvn
if test -z "$vndev"; then
return 0
fi
cmd_umount
vnconfig -u "$vndev"
}
cmd_startvn()
{
is_running
if test "$?" -eq "0"; then
echo "A virtual kernel is using this image file, sorry"
exit 2
fi
# see if there already exists a vn device for this disk image
getvn
if test ! -z "$vndev"; then
return 0
fi
# get free vn device
if test -z "$vndev"; then
vndev=`vnconfig -l | awk -F':' '/.*: not in use$/ {print $1 ; exit 0}'`
fi
vnconfig -c -s labels "$vndev" "$diskimage"
}
is_mounted()
{
for i in `/sbin/mount | awk '/.* on .*/ {print $3}'`; do
if test "$mountpoint" = "$i"; then
return 0
fi
done
return 1
}
cmd_mount()
{
cmd_startvn
is_mounted
if test "$?" -eq "0"; then
return 0
fi
/sbin/mount /dev/${vndev}s0a $mountpoint
}
cmd_umount()
{
is_mounted
if test "$?" -eq "0"; then
/sbin/umount $mountpoint
fi
}
cmd_iw()
{
cmd_mount
(cd $world && make DESTDIR=$mountpoint installworld)
}
cmd_init()
{
args=`getopt m:s:w:k: $*`
if test "0" -ne "$?"; then
usage
fi
set -- $args
for i; do
case "$i"
in
-m)
mountpoint="$2"
shift; shift;;
-s)
size=$2
shift; shift;;
-w)
world=$2
shift; shift;;
-k)
kernel=$2
shift; shift;;
--)
shift; break;;
esac
done
name=$1
if test -z "$name" -o -z "$world" -o -z "$mountpoint" -o -z "$kernel"; then
usage
fi
printf "[$name]\n"
printf "mountpoint=%s\n" $mountpoint
printf "world=%s\n" $world
printf "kernel=%s\n" $kernel
configfile="$HOME/.vkernels/$name"
if test -f "$configfile"; then
echo "vkernel config \"$name\" already exists" 1>&2
exit 2
fi
diskimage="/var/vkernel/$name.rootimg"
if test ! -d "$HOME/.vkernels"; then
mkdir "$HOME/.vkernels"
if test "$?" -eq "0"; then
echo "can't create $HOME/.vkernels"
exit 1
fi
fi
printf 'diskimage=%s\n' "$diskimage" >> $configfile
printf 'memory=%s\n' "64m" >> $configfile
printf 'mountpoint=%s\n' "$mountpoint" >> $configfile
printf 'world=%s\n' "$world" >> $configfile
printf 'kernel=%s\n' "$kernel" >> $configfile
if test ! -z "$kernelconfig"; then
printf 'kernelconfig=%s' "$kernelconfig" >> $configfile
fi
dd if=/dev/zero of=$diskimage bs=1m count=$size
cmd_startvn # sets vndev
disklabel -r -w ${vndev}s0 auto
partsize=`disklabel ${vndev}s0 | awk '/^ c:.*/ {print $2}'`
(disklabel ${vndev}s0 ; echo " a: $partsize 0 4.2BSD") | disklabel -R ${vndev}s0 /dev/stdin
newfs ${vndev}s0a
cmd_iw
(cd $world/etc && make DESTDIR=$mountpoint distribution)
printf "/dev/%ss0a\t/\tufs\trw\t1\t1\n" >> $mountpoint/etc/fstab
printf "proc\t/proc\tprocfs\trw\t0\t0\n" >> $mountpoint/etc/fstab
# fugly
cat /etc/ttys | awk '// {if ($1 == "console") print "console \"/usr/libexec/getty Pc\" cons25 on secure"; else if ($2 == "\"/usr/libexec/getty") print $1, $2, $3, $4, "off", $6; else print $0}' > $mountpoint/etc/ttys
}
cmd_run()
{
cmd_stopvn
is_running
if test "$?" -eq "0"; then
echo "The vkernel is already running"
exit 2
fi
for i in $*; do
echo $i
done
$kernel -p /var/run/vkernel_${name}.pid -m $memory -r $diskimage $*
}
cmd_halt()
{
if test ! -f "/var/run/vkernel_${name}.pid"; then
echo "Not running"
exit 2
fi
kill `cat /var/run/vkernel_${name}.pid`
}
cmd_kill()
{
if test ! -f "/var/run/vkernel_${name}.pid"; then
echo "Not running"
exit 2
fi
kill -9 `cat /var/run/vkernel_${name}.pid`
rm -f /var/run/vkernel_${name}.pid
}
cmd="$1"
if test -z "$cmd"; then
usage
fi
case "$cmd" in
startvn|stopvn|iw|mount|umount|run|halt|kill)
shift
loadconf $*
shift # get rid of config name
# while mount is a reasonable name, defining e.g. mount()
# shadows the mount command, which may lead to silly
# bugs. FIXME: kill eval
eval "cmd_${cmd}" $*
break
;;
init)
shift
cmd_init $*
break
;;
*)
printf "unsupported command: %s\n" $cmd
usage
esac
exit 0
More information about the Kernel
mailing list