diff options
| author | Martin Pitt <martin.pitt@ubuntu.com> | 2015-11-12 11:58:24 (GMT) |
|---|---|---|
| committer | Martin Pitt <martin.pitt@ubuntu.com> | 2015-11-12 11:59:28 (GMT) |
| commit | 609c9949a1053efd720039689116e0aea1b33738 (patch) | |
| tree | 50707fb613f7abd83d9d9721a085bacd14efa582 | |
| parent | 64fd142226f698b807eab259592f426d1863a881 (diff) | |
Better handle transient apt download errors
Detect if apt fails to download packages (as opposed to installing them), retry
up to three times, and eventually fail with exit code 16. This avoids failing
tests due to DNS/infrastructure problems and handling them as tmpfails instead.
| -rw-r--r-- | debian/changelog | 4 | ||||
| -rw-r--r-- | lib/adt_testbed.py | 26 | ||||
| -rwxr-xr-x | tests/adt-run | 2 |
3 files changed, 26 insertions, 6 deletions
diff --git a/debian/changelog b/debian/changelog index 828fc4e..5abd65c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,10 @@ autopkgtest (3.18.1) UNRELEASED; urgency=medium * With --apt-pocket=POCKET=pkgname,... also include <release>-updates. * cloud-vm-setup, adt-setup-vm: Disable /etc/cron.daily/apt. + * Detect if apt fails to download packages (as opposed to installing them), + retry up to three times, and eventually fail with exit code 16. This + avoids failing tests due to DNS/infrastructure problems and handling them + as tmpfails instead. -- Martin Pitt <mpitt@debian.org> Wed, 11 Nov 2015 22:56:46 +0100 diff --git a/lib/adt_testbed.py b/lib/adt_testbed.py index 9f55503..e472b33 100644 --- a/lib/adt_testbed.py +++ b/lib/adt_testbed.py @@ -468,14 +468,30 @@ Description: satisfy autopkgtest test dependencies # install it and its dependencies in the tb; our apt pinning is not # very clever wrt. resolving transitional dependencies in the pocket, # so we might need to retry without pinning + download_fail_retries = 3 while True: self.check_exec(['dpkg', '--unpack', deb.tb], stdout=subprocess.PIPE) - rc = self.execute(self.eatmydata_prefix + - ['apt-get', 'install', '--assume-yes', '--fix-broken', - '-o', 'APT::Install-Recommends=%s' % recommends, - '-o', 'Debug::pkgProblemResolver=true'], - kind='install')[0] + # capture status-fd to stderr + (rc, _, serr) = self.execute(['/bin/sh', '-ec', '%s apt-get install ' + '--assume-yes --fix-broken ' + '-o APT::Status-Fd=3 ' + '-o APT::Install-Recommends=%s ' + '-o Debug::pkgProblemResolver=true 3>&2 2>&1' % + (' '.join(self.eatmydata_prefix), recommends)], + kind='install', stderr=subprocess.PIPE) if rc != 0: + adtlog.debug('apt-get install failed; status-fd:\n%s' % serr) + # check if apt failed during package download, which might be a + # transient error, so retry + if 'dlstatus:' in serr and 'pmstatus:' not in serr: + download_fail_retries -= 1 + if download_fail_retries > 0: + adtlog.warning('apt failed to download packages, retrying in 10s...') + time.sleep(10) + continue + else: + self.bomb('apt repeatedly failed to download packages') + if shell_on_failure: self.run_shell() self.badpkg('failed to run apt-get to satisfy adt-satdep.deb dependencies') diff --git a/tests/adt-run b/tests/adt-run index 03abe4f..cb616f6 100755 --- a/tests/adt-run +++ b/tests/adt-run @@ -2453,7 +2453,7 @@ class SchrootRunner(AdtTestCase): (code, out, err) = self.adt_run(['--no-built-binaries', '--unbuilt-tree=' + p]) self.assertEqual(code, 12, err) - self.assertRegex(err, '[dD]epends.*unknown', err) + self.assertRegex(out, '[dD]epends.*unknown', err) self.assertRegex(err, 'Test dependencies are unsatisfiable', err) self.assertRegex(out, 'blame: .*/testpkg', out) self.assertRegex(out, 'Test dependencies are unsatisfiable', out) |
