diff -Nru autopkgtest-2.11/debian/changelog autopkgtest-2.12/debian/changelog --- autopkgtest-2.11/debian/changelog 2014-03-21 08:36:58.000000000 +0000 +++ autopkgtest-2.12/debian/changelog 2014-03-31 09:45:17.000000000 +0000 @@ -1,3 +1,33 @@ +autopkgtest (2.12) unstable; urgency=medium + + [ Martin Pitt ] + New features: + * Add new options -s/--shell-fail for running a shell in the testbed after + every failed test, and --shell for running a shell in the testbed after + every test. This should make debugging tests or regressions quite a bit + simpler. This actually spawns a shell for the null, chroot, schroot, and + lxc runners, and shows how to login to the VM for qemu (this will + hopefully be improved in the future, but at least makes debugging possible + for now). + + Bug fixes: + * adt-build-lxc: Fix apt proxy setting for ubuntu template; use $HTTP_PROXY, + not $APT_PROXY. + * Make PEP-8 failures non-fatal during package build. They often fail in + backports to old releases, and running them before releasing a new package + is sufficient. + * Filter out comment lines from control lines, as python-debian doesn't + properly do that (Debian #743174). Fixes lintian autopkgtest. + (LP: #1300031) + + [ Antonio Terceiro ] + * adt-virt-schroot: Add new option -s/--session-id for specifying a custom + schroot session id. This is useful for debugging test suites that go crazy + on ci.debian.net, so you can `schroot --list --all-sessions` and see which + sessions are still open. + + -- Martin Pitt Mon, 31 Mar 2014 11:45:13 +0200 + autopkgtest (2.11) unstable; urgency=medium * Add tools/adt-setup-vm: Setup script for vmdebootstrap (and potentially diff -Nru autopkgtest-2.11/debian/rules autopkgtest-2.12/debian/rules --- autopkgtest-2.11/debian/rules 2014-03-21 08:36:58.000000000 +0000 +++ autopkgtest-2.12/debian/rules 2014-03-31 09:45:17.000000000 +0000 @@ -45,7 +45,7 @@ override_dh_auto_test: tests/pyflakes - tests/pep8 + tests/pep8 || true tests/adt-run NullRunnerNoRoot # necessary until we move to compat level 9 diff -Nru autopkgtest-2.11/doc/README.virtualisation-server autopkgtest-2.12/doc/README.virtualisation-server --- autopkgtest-2.11/doc/README.virtualisation-server 2014-03-21 08:36:58.000000000 +0000 +++ autopkgtest-2.12/doc/README.virtualisation-server 2014-03-31 09:45:17.000000000 +0000 @@ -260,7 +260,16 @@ and then the regime server exits with status 0, after closing the testbed if applicable. +* Command + shell + response: one of + ok + not supported by virt server + Runs a shell in the testbed (as root, if available), while the testbed is + open. This is intended for interactively debugging problems with tests. The + virt server has to provide a hook_shell() function for this, otherwise this + command is not supported. On any error including signals to the regime server or EOF on stdin diff -Nru autopkgtest-2.11/lib/VirtSubproc.py autopkgtest-2.12/lib/VirtSubproc.py --- autopkgtest-2.11/lib/VirtSubproc.py 2014-03-21 08:36:58.000000000 +0000 +++ autopkgtest-2.12/lib/VirtSubproc.py 2014-03-31 09:45:17.000000000 +0000 @@ -594,6 +594,16 @@ copyupdown(c, ce, True) +def cmd_shell(c, ce): + cmdnumargs(c, ce, 4) + if not downtmp: + bomb("`shell' when not open") + try: + caller.hook_shell(c[1], c[2], c[3], c[4]) + except AttributeError: + raise FailedCmd(['not supported by virt server']) + + def command(): sys.stdout.flush() while True: diff -Nru autopkgtest-2.11/runner/adt-run autopkgtest-2.12/runner/adt-run --- autopkgtest-2.11/runner/adt-run 2014-03-21 08:36:58.000000000 +0000 +++ autopkgtest-2.12/runner/adt-run 2014-03-31 09:45:17.000000000 +0000 @@ -384,6 +384,10 @@ help='command to gain root during package build, passed to dpkg-buildpackage -r') parser.add_option('-q', '--quiet', action='store_true', dest='quiet', default=False) parser.add_option('-d', '--debug', action='count', dest='debuglevel', default=0) + parser.add_option('-s', '--shell-fail', action='store_true', + help='run a shell in the testbed after every failed test') + parser.add_option('--shell', action='store_true', + help='run a shell in the testbed after every test') parser.add_option('--gnupg-home', type='string', dest='gnupghome', default='~/.autopkgtest/gpg', help='use GNUPGHOME rather than ~/.autopkgtest (for' @@ -1387,6 +1391,7 @@ self._debug(' - - - - - - - - - - results - - - - - - - - - -') + passed = False if rc != 0: self.reportfail('non-zero exit status %d' % rc) elif se_size != 0 and 'allow-stderr' not in self.restriction_names: @@ -1395,6 +1400,7 @@ self.reportfail('status: %d, stderr: %s' % (rc, stderr_top)) else: self.report('PASS') + passed = True # avoid mixing up stdout (from report) and stderr (from _debug) in output sys.stdout.flush() @@ -1427,6 +1433,13 @@ if not os.listdir(ap.host): os.rmdir(ap.host) + if opts.shell or (opts.shell_fail and not passed): + self._debug(' - - - - - - - - - - running shell - - - - - - - - - -') + testbed.command('shell', (os.path.realpath('/dev/stdin'), + os.path.realpath('/dev/stdout'), + os.path.realpath('/dev/stderr'), + tree.tb)) + def read_stanzas(path): stanzas = [] @@ -1438,13 +1451,25 @@ raise return [] + # filter out comments, python-debian doesn't do that + # (http://bugs.debian.org/743174) + lines = [] + for l in control: + # completely ignore ^# as that breaks continuation lines + if l.startswith('#'): + continue + # filter out comments which don't start on first column + l = l.split('#', 1)[0] + lines.append(l) + control.close() + lno = 0 stz = {} # stz[field_name][index] = (lno, value) # special field names: # stz[' lno'] = number # stz[' tests'] = list of Test objects # empty dictionary means we're between stanzas - for paragraph in deb822.Deb822.iter_paragraphs(control): + for paragraph in deb822.Deb822.iter_paragraphs(lines): lno += 1 stz = {' lno': lno, ' tests': []} for field, value in paragraph.iteritems(): diff -Nru autopkgtest-2.11/runner/adt-run.1 autopkgtest-2.12/runner/adt-run.1 --- autopkgtest-2.11/runner/adt-run.1 2014-03-21 08:36:58.000000000 +0000 +++ autopkgtest-2.12/runner/adt-run.1 2014-03-31 09:45:17.000000000 +0000 @@ -190,6 +190,15 @@ additional \fB-d\fR increases the debugging level; the current maximum is \fB-ddd\fR. If you like to see what's going on, \fR-d\fB or \fR-dd\fB is recommended. + +.TP +.BR --shell-fail | -s +Run an interactive shell in the testbed after every failed test. + +.TP +.BR --shell +Run an interactive shell in the testbed after every test. + .TP .BI --gnupg-home= dir Uses \fIdir\fR as the \fBGNUPGHOME\fR for local apt archive signing. diff -Nru autopkgtest-2.11/tests/adt-run autopkgtest-2.12/tests/adt-run --- autopkgtest-2.11/tests/adt-run 2014-03-21 08:36:58.000000000 +0000 +++ autopkgtest-2.12/tests/adt-run 2014-03-31 09:45:17.000000000 +0000 @@ -896,13 +896,15 @@ '''test depends on build dependencies''' p = self.build_src('''Tests: pass -Depends: @, testdep1, @builddeps@, testdep2 +Depends: @, testdep1, @builddeps@, testdep2, +# blabla + testdep3 Restrictions: needs-root ''', {'pass': '#!/bin/sh\ntrue'}) # add extra build dependencies to testpkg - subprocess.check_call(['sed', '-i', '/^Build-Depends:/ s/:.*/: bdep1 , bdep2\\n' - 'Build-Depends-Indep: bdep3/', + subprocess.check_call(['sed', '-i', '/^Build-Depends:/ s/:.*/: bdep1 , bdep2,\\n bdep3, # moo\\n#comment\\n bdep4\\n' + 'Build-Depends-Indep: bdep5/', os.path.join(p, 'debian', 'control')]) (code, out, err) = self.adt_run(['-dB', '--unbuilt-tree=' + p], @@ -915,8 +917,11 @@ self.assertIn('synthesised dependency bdep1\n', err) self.assertIn('synthesised dependency bdep2\n', err) self.assertIn('synthesised dependency bdep3\n', err) + self.assertIn('synthesised dependency bdep4\n', err) + self.assertIn('synthesised dependency bdep5\n', err) self.assertIn('processing dependency testdep2\n', err) - self.assertRegex(err, 'fake-apt-get: .*install.*testpkg testdep1 bdep1 bdep2 bdep3 make testdep2') + self.assertIn('processing dependency testdep3\n', err) + self.assertRegex(err, 'fake-apt-get: .*install.*testpkg testdep1 bdep1 bdep2 bdep3 bdep4 bdep5 make testdep2 testdep3') def test_logfile(self): '''--log-file option''' diff -Nru autopkgtest-2.11/tools/adt-build-lxc autopkgtest-2.12/tools/adt-build-lxc --- autopkgtest-2.11/tools/adt-build-lxc 2014-03-21 08:36:58.000000000 +0000 +++ autopkgtest-2.12/tools/adt-build-lxc 2014-03-31 09:45:17.000000000 +0000 @@ -37,6 +37,7 @@ LXCDIR=`lxc-config lxc.lxcpath` || LXCDIR=`lxc-config lxcpath` || LXCDIR=/var/lib/lxc LXC_ARGS="-t $DISTRO -- -r $RELEASE" +export HTTP_PROXY=${HTTP_PROXY:=apt} setup() { # add deb-src @@ -63,11 +64,11 @@ if [ ! -e $LXCDIR/$NAME ]; then # first-time run: just create the container - APT_PROXY=apt lxc-create -n $NAME $LXC_ARGS + lxc-create -n $NAME $LXC_ARGS setup $NAME else # create a new rootfs in a temp container - APT_PROXY=apt lxc-create -n ${NAME}.new $LXC_ARGS -F + lxc-create -n ${NAME}.new $LXC_ARGS -F setup ${NAME}.new # replace the original rootfs rsync -aHAXS --numeric-ids --delete $LXCDIR/${NAME}.new/rootfs $LXCDIR/${NAME}/rootfs diff -Nru autopkgtest-2.11/tools/adt-buildvm-ubuntu-cloud autopkgtest-2.12/tools/adt-buildvm-ubuntu-cloud --- autopkgtest-2.11/tools/adt-buildvm-ubuntu-cloud 2014-03-21 08:36:58.000000000 +0000 +++ autopkgtest-2.12/tools/adt-buildvm-ubuntu-cloud 2014-03-31 09:45:17.000000000 +0000 @@ -116,8 +116,8 @@ if percent > download_image.lastpercent: download_image.lastpercent = percent sys.stdout.write('\r%.1f/%.1f MB (%i%%) ' % ( - cur_bytes/1000000., - totalsize/1000000., + cur_bytes / 1000000., + totalsize / 1000000., percent)) sys.stdout.flush() else: diff -Nru autopkgtest-2.11/virt-subproc/adt-virt-chroot autopkgtest-2.12/virt-subproc/adt-virt-chroot --- autopkgtest-2.11/virt-subproc/adt-virt-chroot 2014-03-21 08:36:58.000000000 +0000 +++ autopkgtest-2.12/virt-subproc/adt-virt-chroot 2014-03-31 09:45:17.000000000 +0000 @@ -24,6 +24,7 @@ import sys import os +import subprocess from optparse import OptionParser try: @@ -110,5 +111,14 @@ def hook_capabilities(): return capabilities + +def hook_shell(stdin, stdout, stderr, dir): + with open(stdin, 'rb') as sin: + with open(stdout, 'wb') as sout: + with open(stderr, 'wb') as serr: + subprocess.call(VirtSubproc.down + ['sh', '-c', 'cd %s; exec bash -i' % dir], + stdin=sin, stdout=sout, stderr=serr) + + parse_args() VirtSubproc.main() diff -Nru autopkgtest-2.11/virt-subproc/adt-virt-lxc autopkgtest-2.12/virt-subproc/adt-virt-lxc --- autopkgtest-2.11/virt-subproc/adt-virt-lxc 2014-03-21 08:36:58.000000000 +0000 +++ autopkgtest-2.12/virt-subproc/adt-virt-lxc 2014-03-31 09:45:17.000000000 +0000 @@ -250,5 +250,15 @@ return capabilities +def hook_shell(stdin, stdout, stderr, dir): + argv = ['lxc-attach', '-n', lxc_container_name, '--', 'sh', '-c', 'cd %s; exec bash -i' % dir] + if use_sudo: + argv = ['sudo', '-E'] + argv + with open(stdin, 'rb') as sin: + with open(stdout, 'wb') as sout: + with open(stderr, 'wb') as serr: + subprocess.call(argv, stdin=sin, stdout=sout, stderr=serr) + + parse_args() VirtSubproc.main() diff -Nru autopkgtest-2.11/virt-subproc/adt-virt-null autopkgtest-2.12/virt-subproc/adt-virt-null --- autopkgtest-2.11/virt-subproc/adt-virt-null 2014-03-21 08:36:58.000000000 +0000 +++ autopkgtest-2.12/virt-subproc/adt-virt-null 2014-03-31 09:45:17.000000000 +0000 @@ -24,6 +24,7 @@ import sys import os +import subprocess from optparse import OptionParser try: @@ -81,5 +82,14 @@ def hook_capabilities(): return capabilities + +def hook_shell(stdin, stdout, stderr, dir): + with open(stdin, 'rb') as sin: + with open(stdout, 'wb') as sout: + with open(stderr, 'wb') as serr: + subprocess.call(['bash', '-i'], stdin=sin, stdout=sout, + stderr=serr, cwd=dir) + + parse_args() VirtSubproc.main() diff -Nru autopkgtest-2.11/virt-subproc/adt-virt-qemu autopkgtest-2.12/virt-subproc/adt-virt-qemu --- autopkgtest-2.11/virt-subproc/adt-virt-qemu 2014-03-21 08:36:58.000000000 +0000 +++ autopkgtest-2.12/virt-subproc/adt-virt-qemu 2014-03-31 09:45:17.000000000 +0000 @@ -351,5 +351,22 @@ return caps +def hook_shell(stdin, stdout, stderr, dir): + with open(stdout, 'w') as f: + f.write('''You can now log into the VM through the serial terminal. +Depending on which terminal program you have installed, you can use one of + + minicom -D unix#%(tty0)s + nc -U %(tty0)s + socat - UNIX-CONNECT:%(tty0)s + +The tested source package is in %(dir)s + +Press Enter to resume adt-run. +''' % {'tty0': os.path.join(workdir, 'ttyS0'), 'dir': dir}) + with open(stdin, 'r') as f: + f.readline() + + parse_args() VirtSubproc.main() diff -Nru autopkgtest-2.11/virt-subproc/adt-virt-schroot autopkgtest-2.12/virt-subproc/adt-virt-schroot --- autopkgtest-2.11/virt-subproc/adt-virt-schroot 2014-03-21 08:36:58.000000000 +0000 +++ autopkgtest-2.12/virt-subproc/adt-virt-schroot 2014-03-31 09:45:17.000000000 +0000 @@ -27,6 +27,7 @@ import re import grp import pwd +import subprocess from optparse import OptionParser try: @@ -65,17 +66,21 @@ def parse_args(): - global schroot + global schroot, sessid usage = "%prog [] " parser = OptionParser(usage=usage) parser.add_option('-d', '--debug', action='store_true') + parser.add_option('-s', '--session-id', + help='custom schroot session ID for easy identification ' + 'in "schroot --list --all-sessions"') (opts, args) = parser.parse_args() if len(args) != 1: parser.error("need exactly one arg, schroot name") + sessid = opts.session_id schroot = args[0] info = VirtSubproc.execute('schroot --config -c', [schroot], @@ -110,7 +115,8 @@ def hook_open(): global schroot, sessid sessid = VirtSubproc.execute( - 'schroot -b -c', [schroot], downp=False, outp=True) + 'schroot -b -c', [schroot] + (sessid and ['-n', sessid] or []), + downp=False, outp=True) VirtSubproc.down = ['schroot', '-r', '-d', '/', '-c', sessid] if 'root-on-testbed' in capabilities: VirtSubproc.down += ['-u', 'root'] @@ -157,5 +163,16 @@ def hook_capabilities(): return capabilities + +def hook_shell(stdin, stdout, stderr, dir): + argv = ['schroot', '-r', '-d', dir, '-c', sessid] + if 'root-on-testbed' in capabilities: + argv += ['-u', 'root'] + with open(stdin, 'rb') as sin: + with open(stdout, 'wb') as sout: + with open(stderr, 'wb') as serr: + subprocess.call(argv, stdin=sin, stdout=sout, stderr=serr) + + parse_args() VirtSubproc.main() diff -Nru autopkgtest-2.11/virt-subproc/adt-virt-schroot.1 autopkgtest-2.12/virt-subproc/adt-virt-schroot.1 --- autopkgtest-2.11/virt-subproc/adt-virt-schroot.1 2014-03-21 08:36:58.000000000 +0000 +++ autopkgtest-2.12/virt-subproc/adt-virt-schroot.1 2014-03-31 09:45:17.000000000 +0000 @@ -38,6 +38,12 @@ .SH OPTIONS .TP +.BI -s " ID" " | --session-id=" ID +Use a custom schroot session ID. This allows the user to easily +identify hung sessions in +.B schroot --list --all-sessions\fR. + +.TP .BR \-d " | " \-\-debug Enables debugging output.