chiark / gitweb /
WIP userv service and print-execute-command
authorIan Jackson <ian@anarres>
Fri, 18 May 2007 15:56:45 +0000 (16:56 +0100)
committerIan Jackson <ian@anarres>
Fri, 18 May 2007 15:56:45 +0000 (16:56 +0100)
debian/changelog
debian/rules
doc/README.virtualisation-server
settings.make
virt-subproc/VirtSubproc.py
virt-subproc/adt-virt-xenlvm
virt-subproc/adt-virt-xenlvm.1
xen/Makefile
xen/on-testbed
xen/userv-fragment
xen/userv-target

index dd6992554be599679811473f8d9b05d471eafb90..a6025405d5373e952161ac3752948e2a5e968a26 100644 (file)
@@ -1,8 +1,9 @@
 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
 
index 00145e0afbd6b38c367a30a22c396ed2d85c9767..e3e98f3d6400fabe697a7e7a7b8614ab96d25c06 100755 (executable)
@@ -46,6 +46,8 @@ binary binary-indep: checkdir
                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 \
index e01137e591b0c3127622296ec0e496fa848288c9..d391d6507e839f777e4fd97beab5d4723c3bb459 100644 (file)
@@ -63,6 +63,11 @@ Protocol
        (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
@@ -91,6 +96,66 @@ Protocol
   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> ...]
index 0ddf956a77c24c875f9bcff4403f30c5cbc2478c..92fc08bee26c4cf0655acbdc6e66987e0f8b8ca3 100644 (file)
@@ -12,6 +12,8 @@ sharedir_lnfrom = $(share)/$(pkgname)
 etcdir =       /etc
 etcconfdir =   $(etcdir)/autopkgtest
 etcinitddir =  $(etcdir)/init.d
+etcuservdir =  $(etcdir)/userv
+uservsvcdir =  $(etcuservdir)/services.d
 xenscripts =   $(etcdir)/xen/scripts
 cfg_suffix =   .dist
 
index 9f16c4b0ddb23db0c4b2dd8f1e69e664011891b8..9b3c36f97f44b134d5bdc88429eddb60fd4bcf1b 100644 (file)
@@ -65,7 +65,8 @@ def cmdnumargs(c, ce, nargs=0, noptargs=0):
 
 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)
@@ -76,6 +77,16 @@ def cmd_close(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()
 
@@ -315,7 +326,8 @@ def command():
        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)
index dc9795d3112a0003ac346c330a98a99476ba895f..46ee14e76aa587222f74f228d3403a5bbb55d9f0 100755 (executable)
@@ -57,32 +57,60 @@ def check_pause(kind):
        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()
index c8310480fba5096f52ac2b8c6544d869a947bbe2..396d4b1c53544eb1563765c4a11ef8b0e052dd3a 100644 (file)
@@ -35,8 +35,19 @@ do any locking; it is the the caller's responsibility not to attempt
 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
@@ -44,12 +55,25 @@ 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
index 200e031ca110296d33f5f309525650fbd4fbd7fc..853db49d312569c99ae362650621f7d215b9c66c 100644 (file)
@@ -23,7 +23,7 @@
 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-
@@ -44,6 +44,8 @@ install:      all
        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)
index 74f94da809d9b7e340fcfd70b910e075fdd991e3..60eabd5afe3a025aed9c2dcc1324fa5779f32062 100755 (executable)
@@ -3,4 +3,13 @@ set -e
 . ${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 "$@"
index ad0dd4142cb91bf159ce1f3c7d97babe84cecc41..d18dd9fbcfbfb90d523aafa070dc35ebd2dd2702 100644 (file)
@@ -4,5 +4,6 @@ if ( glob calling-group AdtXenUs root
        reset
        no-set-environment
        no-disconnect-hup
+       no-suppress-args
        execute /usr/share/autopkgtest/xenlvm/userv-target
 fi
index e9ad631ac0cf3cb7382e09b56b149bcc54cdfc56..1b874f340c45ee3cd41936e0914f64e92ab25aea 100755 (executable)
@@ -1,8 +1,27 @@
 #!/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