summaryrefslogtreecommitdiff
path: root/cloudinit/gpg.py
diff options
context:
space:
mode:
authorKim Hagen <kim.sidney@gmail.com>2018-10-25 22:26:25 +0200
committerKim Hagen <kim.sidney@gmail.com>2018-10-25 22:26:25 +0200
commitb120f4f7a670674779a93f8c882c81f44a993888 (patch)
tree906d15f6520751b5e8fbeb49b680e673a5cc6aa3 /cloudinit/gpg.py
parent838581d57c8765d3e487f58bc37ea103af39d26f (diff)
parent833adcdf6f85ec2305e62bea5a20f9363bf95507 (diff)
downloadvyos-cloud-init-b120f4f7a670674779a93f8c882c81f44a993888.tar.gz
vyos-cloud-init-b120f4f7a670674779a93f8c882c81f44a993888.zip
Merge tag 'ubuntu/18.4-0ubuntu1_16.04.2' into current
Conflicts: cloudinit/sources/DataSourceAzure.py config/cloud.cfg.tmpl integration-requirements.txt tools/read-version
Diffstat (limited to 'cloudinit/gpg.py')
-rw-r--r--cloudinit/gpg.py52
1 files changed, 42 insertions, 10 deletions
diff --git a/cloudinit/gpg.py b/cloudinit/gpg.py
index d58d73e0..7fe17a2e 100644
--- a/cloudinit/gpg.py
+++ b/cloudinit/gpg.py
@@ -10,6 +10,8 @@
from cloudinit import log as logging
from cloudinit import util
+import time
+
LOG = logging.getLogger(__name__)
@@ -25,16 +27,46 @@ def export_armour(key):
return armour
-def recv_key(key, keyserver):
- """Receive gpg key from the specified keyserver"""
- LOG.debug('Receive gpg key "%s"', key)
- try:
- util.subp(["gpg", "--keyserver", keyserver, "--recv", key],
- capture=True)
- except util.ProcessExecutionError as error:
- raise ValueError(('Failed to import key "%s" '
- 'from server "%s" - error %s') %
- (key, keyserver, error))
+def recv_key(key, keyserver, retries=(1, 1)):
+ """Receive gpg key from the specified keyserver.
+
+ Retries are done by default because keyservers can be unreliable.
+ Additionally, there is no way to determine the difference between
+ a non-existant key and a failure. In both cases gpg (at least 2.2.4)
+ exits with status 2 and stderr: "keyserver receive failed: No data"
+ It is assumed that a key provided to cloud-init exists on the keyserver
+ so re-trying makes better sense than failing.
+
+ @param key: a string key fingerprint (as passed to gpg --recv-keys).
+ @param keyserver: the keyserver to request keys from.
+ @param retries: an iterable of sleep lengths for retries.
+ Use None to indicate no retries."""
+ LOG.debug("Importing key '%s' from keyserver '%s'", key, keyserver)
+ cmd = ["gpg", "--keyserver=%s" % keyserver, "--recv-keys", key]
+ if retries is None:
+ retries = []
+ trynum = 0
+ error = None
+ sleeps = iter(retries)
+ while True:
+ trynum += 1
+ try:
+ util.subp(cmd, capture=True)
+ LOG.debug("Imported key '%s' from keyserver '%s' on try %d",
+ key, keyserver, trynum)
+ return
+ except util.ProcessExecutionError as e:
+ error = e
+ try:
+ naplen = next(sleeps)
+ LOG.debug(
+ "Import failed with exit code %d, will try again in %ss",
+ error.exit_code, naplen)
+ time.sleep(naplen)
+ except StopIteration:
+ raise ValueError(
+ ("Failed to import key '%s' from keyserver '%s' "
+ "after %d tries: %s") % (key, keyserver, trynum, error))
def delete_key(key):