autopkgtest (0.9.0~iwj) unstable; urgency=low
* WIP userv service.
+ * WIP print-execute-command command for virtualisation servers.
- --
+ -- Ian Jackson <ian@davenant.greenend.org.uk> Fri, 18 May 2007 16:56:44 +0100
autopkgtest (0.8.2feisty1~iwj) feisty-updates; urgency=low
sharedir_lnfrom=/usr/share/$p/$x \
sharedir=$(topdir)/debian/$p-$x/usr/share/$p/$x \
etcdir=$(topdir)/debian/$p-$x/etc cfg_suffix=''
+ cd debian/$p-$x/etc/userv/rules.d && \
+ mv -f adt-xenlvm-testbed adt-xenlvm-testbed:dist
set -e; for f in $p $p-$x; do \
cat CREDITS debian/copyright.suffix \
(with distinct <username>s) may be advertised in which case
more than one such user is available.
+ + print-execute-command
+ The 'print-execute-command' command is available, so that the
+ caller can execute multiple concurrent commands on the testbed
+ with asynchronous input and output, if desired.
+
* Command
open
advertised). State: Open to Closed.
+* Command
+ print-execute-command
+ response
+ ok <program>,<arg>,<arg>... auxverb|shstring [<keyword-info> ...]
+ Prints a command that can be executed by the caller to run a command
+ on the testbed. Only available if the `print-execute-command'
+ capability is advertised.
+
+ The command has the following properties (which are, for example,
+ satisfiable when the virt server uses `env' `ssh' or `dchroot'):
+ - The caller is expected to url-decode <program> and each <arg>,
+ append the command to be run on the testbed, and call exec on the
+ results.
+ - If auxverb is advertised, the supplied additional arguments to
+ command will be interpreted as the command and arguments to be
+ run on the testbed (as env and nice interpret their arguments)
+ - If shstring is advertised, there should be one additional
+ argument which will be fed to sh -c on the testbed (this is the
+ way ssh interprets its arguments).
+ - The testbed program's stdin, stdout and stderr will be plumbed
+ through to the stdin, stdout and stderr passed to <program>; this
+ may involve fd passing, or indirection via pipes or sockets. The
+ testbed program may not assume that the descriptors it receives
+ are seekable even if the originals are.
+ - It is not defined whether other file descriptors, environment
+ variables, and process properties in general, are inherited by
+ the testbed command.
+ - <program> may exit as soon as the testbed command does, or it may
+ wait until every copy of the stdout and stderr descriptors passed
+ to the testbed command have been closed on the testbed.
+ - <program>'s exit status will be that of the testbed command if
+ the latter exits with a value from 0..125. If the testbed
+ command dies due to a signal, then either (i) <program> will exit
+ with the signal number with 128 added, or (ii) <program> will die
+ with the same signal (although it may fail to dump core even if
+ the testbed program did), or (iii) <program> will fail. If
+ <program> fails it will exit 126, 127, 254, or 255; of course
+ <program> may die to a some signals other than because the
+ testbed program died with the same signal.
+ - The caller may run several of these at once, subject to
+ limitation of resources (eg, file descriptors, processes)
+ - The behaviour if a command is running when the testbed is closed
+ or reverted is not defined. However, if the testbed advertises
+ `revert' then after the testbed is closed or reverted any such
+ <program> invocation will not have any further effect on the
+ testbed.
+ - Sending <program> signals in an attempt to terminate it may not
+ terminate all of the relevant processes and may not have any
+ effect on the testbed.
+ - The behaviour if no testbed command is specified (ie, if
+ just the specified <program> and <arg>s is passed to exec) is
+ not defined.
+ - Currently no <keyword-info>s are defined; they work the same
+ way as capabilities in that unrecognised ones should be ignored
+ by the caller.
+ The response (ie, the <command>) is only valid between `open' and
+ the next subsequent `close', `revert' or `quit'. Using it at other
+ times has undefined behaviour.
+
+
* Command
execute <program>,<arg>,<arg>... <stdin> <stdout> <stderr> <cwd> \
[<keyword-args> ...]
etcdir = /etc
etcconfdir = $(etcdir)/autopkgtest
etcinitddir = $(etcdir)/init.d
+etcuservdir = $(etcdir)/userv
+uservsvcdir = $(etcuservdir)/services.d
xenscripts = $(etcdir)/xen/scripts
cfg_suffix = .dist
def cmd_capabilities(c, ce):
cmdnumargs(c, ce)
- return caller.hook_capabilities() + ['execute-debug']
+ return caller.hook_capabilities() + ['execute-debug',
+ 'print-execute-command']
def cmd_quit(c, ce):
cmdnumargs(c, ce)
if not downtmp: bomb("`close' when not open")
cleanup()
+def cmd_print_execute_command(c, ce):
+ cmdnumargs(c, ce)
+ if not downtmp: bomb("`print-execute-command' when not open")
+ if hasattr(caller,'hook_callerexeccmd'):
+ (cl,kvl) = caller.hook_callerexeccmd()
+ else
+ cl = down
+ kvl = ['auxverb']
+ return ','.join(map(urllib.quote, cl)) + kvl
+
def preexecfn():
caller.hook_forked_inchild()
c = map(urllib.unquote, ce)
if not c: bomb('empty commands are not permitted')
debug('executing '+string.join(ce))
- try: f = globals()['cmd_'+c[0]]
+ c_lookup = c[0].replace('-','_')
+ try: f = globals()['cmd_'+c_lookup]
except KeyError: bomb("unknown command `%s'" % ce[0])
try:
r = f(c, ce)
os.kill(0, signal.SIGSTOP)
def parse_args():
- global debuglevel, xlargs, gain_root, console, pauses
+ global debuglevel, with_testbed, console, pauses
usage = "%prog <options> [-- <adt-xenlvm options>]"
parser = OptionParser(usage=usage)
pa = parser.add_option
pe = parser.error
- pa('-r', '--gain-root', type='string', dest='gain_root');
- pa('-d', '--debug', action='store_true', dest='debug');
- pa('','--pause', type='string', dest='pause', default='');
+ pa('-r', '--gain-root', type='string', dest='gain_root')
+ pa('-d', '--debug', action='store_true', dest='debug')
+ pa('', '--userv', action='store_true', dest='userv')
+ pa('', '--distro', type='string', dest='distro')
+ pa('', '--nominum', type='string', dest='nominum')
+ pa('','--pause', type='string', dest='pause', default='')
(opts,xlargs) = parser.parse_args()
vsp.debuglevel = opts.debug
-
- if opts.gain_root is None: gain_root = []
- else: gain_root = opts.gain_root.split()
- vsp.down = gain_root + ['adt-xenlvm-on-testbed'] + xlargs + ['--']
-
+ xargs_userv = []
+ xargs_direct = []
+
+ for k in ['distro','nominum']:
+ v = getattr(opts,k)
+ if v is None: continue
+ xargs_direct.append('--%s=%s' % (k, v))
+ xargs_userv.append('-D%s=%s' % (k, v))
+
+ if not opts.userv:
+ if opts.gain_root is None: gain_root = []
+ else: gain_root = opts.gain_root.split()
+ with_testbed = gain_root + ['adt-xenlvm-with-testbed'] +
+ xargs_direct + xlargs +
+ ['--','sh','-ec','echo y; exec cat']
+ vsp.down = gain_root + ['adt-xenlvm-on-testbed'] +
+ xargs_direct + xlargs + ['--']
+ else:
+ if opts.gain_root:
+ pe('--userv and --gain-root are not compatible')
+ basis = ['userv'] + xargs_userv + xlargs +
+ ['root','adt-xenlvm-testbed']
+ get_down = subprocess.Popen(basis + ['pon0'],
+ stdin=file('/dev/null'), stdout=subprocess.PIPE,
+ stderr=None)
+ (pon0, _) = get_down.communicate()
+ if get_down.returncode:
+ vsp.bomb('failed to check userv service provision'
+ ' and subcommand details (code=%d) %
+ get_down.returncode)
+ vsp.down = pon0.split('\0')
pauses = opts.pause.split(',')
def do_open():
global withholder
assert(withholder is None)
withholder = subprocess.Popen(
- gain_root + ['adt-xenlvm-with-testbed'] + xlargs +
- ['--','sh','-ec','echo y; exec cat'],
+ with_testbed,
stdin=subprocess.PIPE, stdout=subprocess.PIPE )
l = withholder.stdout.readline(2)
rc = withholder.poll()
concurrent use of any particular testbed.
.SH OPTIONS
.TP
-.BR \-d " | " \-\-debug
-Enables debugging output. Probably not hugely interesting.
+.BI --distro= distro
+Specifies a different distro (ie, the use of a different testbed).
+.TP
+.BI --nominum= nominum
+Specifies a different nominum (ie, the use of a different testbed).
+.TP
+.BR \-\-userv
+Specifies that the adt-xenlvm tools should not be run directly, but
+rather via userv. The calling user must be permitted to use
+.BR "userv root adt-xenlvm-testbed" .
+In the default configuration, this means being a member of the
+.B AdtXenUs
+group.
.TP
.BI "-- --" adt-xenlvm-option = adt-xenlvm-value
Following the first occurrence of
on the
.B adt-virt-xenlvm
commandline, any of the values in the adt-xenlvm configuration may be
-set in the usual way. In particular,
-.BI --nominum= nominum
-can be used to specify the use of a different testbed.
+set in the usual way. The arguments are simply passed to
+\fBadt-virt-xenlvm\fR.
See \fB/usr/share/doc/autopkgtest-xenlvm/README.gz\fR for full details
of adt-xenlvm.
+.TP
+.BI "-- -D" varname = value
+If \fB\-\-userv\fR was specified, options following the first
+.B --
+on the
+.B adt-virt-xenlvm
+commandline are passed as option arguments to \fBuserv\fR. These
+should normally be user-defined variable settings using \fB-D\fR which
+are expected by the \fBautopkgtest-xenlvm/userv-target\fR script.
+Currently only \fBdistro\fR and \fBnominum\fR are expected, and these
+can be set using \fBadt-virt-xenlvm\fR's own options.
+.TP
+.BR \-d " | " \-\-debug
+Enables debugging output. Probably not hugely interesting.
.SH INPUT, OUTPUT AND EXIT STATUS
The behaviour of
.B adt-virt-xenlvm
include ../settings.make
programs = cleanup setup on-testbed with-testbed purge
-shareprograms = fixups fixups-inside
+shareprograms = fixups fixups-inside userv-target
sharefiles = readconfig justconfig
exec_prefix = adt-xenlvm-
set -e; for f in $(sharefiles); do \
$(INSTALL_DATA) $$f $(sharedir); \
done
+ $(INSTALL_DATA) userv-fragment \
+ $(uservsvcdir)/adt-xenlvm-testbed:dist
$(INSTALL_DATA) initscript $(etcinitddir)/adtxenlvm$(cfg_suffix)
$(INSTALL_PROGRAM) vif-route-adt \
$(xenscripts)/vif-route-adt$(cfg_suffix)
. ${ADT_XENLVM_SHARE:=/usr/share/autopkgtest/xenlvm}/justconfig
while test $# -gt $nonoptargs; do shift; done
-ssh $adt_ssh_keyident_args $adt_guest_ipaddr "$@"
+case "$1" in
+x--print-command) ppfx=echo; shift ;;
+x--print0-command) ppfx=ppfx0; shift ;;
+x--) shift ;;
+x-*) fail "invalid instead-of-command options \`$1'" ;;
+esac
+
+ppfx0 () { for x in "$@"; do printf '%s\0' "$x"; done; }
+
+$ppfx ssh $adt_ssh_keyident_args $adt_guest_ipaddr "$@"
reset
no-set-environment
no-disconnect-hup
+ no-suppress-args
execute /usr/share/autopkgtest/xenlvm/userv-target
fi
#!/bin/bash
set -e
-d="$USERV_U_distro"
fail () { printf >&2 "%s: %s\n" "$0" "$*"; exit 127; }
-test "x$d" = "x${d#/*}" || fail 'distro may not contain slashes'
-test -d /var/lib/autopkgtest/xenlvm/adt_"$d" || fail 'unknown distro'
-exec adt-xenlvm-with-testbed --adt-distro="$d" sh -c 'echo y && exec cat'
+. /etc/lsb-release
+
+d="${USERV_U_distro-$DISTRIB_CODENAME}"
+n="${USERV_U_nominum-adt}"
+
+case "$dn" in
+*/*|.*|*.*|*_*_*) fail 'dangerous format in distro or nominum' ;;
+adt*) ;;
+*) fail 'userv adtxenlvm only supports nominums starting with adt' ;;
+esac
+
+test -d /var/lib/autopkgtest/xenlvm/"$dn" || fail 'unknown distro or nominum'
+
+run () {
+ base="$1"; shift
+ exec "$base" --adt-distro="$d" --adt-nominum="$n" "$@"
+}
+
+case "$1" in
+with) run adt-xenlvm-with-testbed sh -c 'echo y && exec cat' ;;
+pon0) run adt-xenlvm-on-testbed -- --print0-command ;;
+*) fail 'unknown mode'
+esac