summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cloudinit/analyze/show.py2
-rwxr-xr-xcloudinit/cmd/devel/make_mime.py6
-rw-r--r--cloudinit/config/cc_disk_setup.py36
-rw-r--r--cloudinit/config/cc_growpart.py8
-rw-r--r--cloudinit/config/cc_power_state_change.py12
-rw-r--r--cloudinit/config/cc_rsyslog.py6
-rw-r--r--cloudinit/config/cc_set_hostname.py2
-rw-r--r--cloudinit/config/cc_ubuntu_advantage.py2
-rw-r--r--cloudinit/config/schema.py2
-rwxr-xr-xcloudinit/distros/__init__.py5
-rw-r--r--cloudinit/distros/arch.py4
-rw-r--r--cloudinit/distros/parsers/resolv_conf.py7
-rw-r--r--cloudinit/gpg.py5
-rw-r--r--cloudinit/handlers/jinja_template.py3
-rw-r--r--cloudinit/net/__init__.py7
-rwxr-xr-xcloudinit/net/cmdline.py4
-rw-r--r--cloudinit/net/dhcp.py4
-rw-r--r--cloudinit/net/network_state.py19
-rwxr-xr-xcloudinit/sources/DataSourceAzure.py2
-rw-r--r--cloudinit/sources/DataSourceEc2.py8
-rw-r--r--cloudinit/sources/DataSourceIBMCloud.py3
-rw-r--r--cloudinit/sources/DataSourceMAAS.py3
-rw-r--r--cloudinit/sources/DataSourceOpenNebula.py13
-rw-r--r--cloudinit/sources/DataSourceOpenStack.py4
-rw-r--r--cloudinit/sources/DataSourceSmartOS.py4
-rwxr-xr-xcloudinit/sources/helpers/azure.py34
-rw-r--r--cloudinit/sources/helpers/netlink.py2
-rw-r--r--cloudinit/sources/helpers/openstack.py34
-rw-r--r--cloudinit/subp.py3
-rw-r--r--cloudinit/url_helper.py6
-rw-r--r--cloudinit/util.py8
-rw-r--r--tests/cloud_tests/platforms/azurecloud/instance.py7
-rw-r--r--tests/cloud_tests/platforms/azurecloud/platform.py23
-rw-r--r--tests/cloud_tests/platforms/ec2/instance.py4
-rw-r--r--tests/cloud_tests/platforms/ec2/platform.py18
-rw-r--r--tests/cloud_tests/platforms/lxd/instance.py3
-rw-r--r--tests/cloud_tests/platforms/platforms.py6
-rw-r--r--tests/cloud_tests/testcases/__init__.py6
-rwxr-xr-xtools/mock-meta.py14
-rw-r--r--tox.ini2
40 files changed, 205 insertions, 136 deletions
diff --git a/cloudinit/analyze/show.py b/cloudinit/analyze/show.py
index 0c825b23..01a4d3e5 100644
--- a/cloudinit/analyze/show.py
+++ b/cloudinit/analyze/show.py
@@ -267,7 +267,7 @@ def gather_timestamps_using_systemd():
except OSError as err:
raise RuntimeError('Could not determine container boot '
'time from /proc/1/cmdline. ({})'
- .format(err))
+ .format(err)) from err
status = CONTAINER_CODE
else:
status = FAIL_CODE
diff --git a/cloudinit/cmd/devel/make_mime.py b/cloudinit/cmd/devel/make_mime.py
index 77e10540..4e6a5778 100755
--- a/cloudinit/cmd/devel/make_mime.py
+++ b/cloudinit/cmd/devel/make_mime.py
@@ -22,8 +22,10 @@ def file_content_type(text):
try:
filename, content_type = text.split(":", 1)
return (open(filename, 'r'), filename, content_type.strip())
- except ValueError:
- raise argparse.ArgumentError(text, "Invalid value for %r" % (text))
+ except ValueError as e:
+ raise argparse.ArgumentError(
+ text, "Invalid value for %r" % (text)
+ ) from e
def get_parser(parser=None):
diff --git a/cloudinit/config/cc_disk_setup.py b/cloudinit/config/cc_disk_setup.py
index d957cfe3..a7bdc703 100644
--- a/cloudinit/config/cc_disk_setup.py
+++ b/cloudinit/config/cc_disk_setup.py
@@ -251,7 +251,9 @@ def enumerate_disk(device, nodeps=False):
try:
info, _err = subp.subp(lsblk_cmd)
except Exception as e:
- raise Exception("Failed during disk check for %s\n%s" % (device, e))
+ raise Exception(
+ "Failed during disk check for %s\n%s" % (device, e)
+ ) from e
parts = [x for x in (info.strip()).splitlines() if len(x.split()) > 0]
@@ -313,7 +315,9 @@ def check_fs(device):
try:
out, _err = subp.subp(blkid_cmd, rcs=[0, 2])
except Exception as e:
- raise Exception("Failed during disk check for %s\n%s" % (device, e))
+ raise Exception(
+ "Failed during disk check for %s\n%s" % (device, e)
+ ) from e
if out:
if len(out.splitlines()) == 1:
@@ -428,8 +432,8 @@ def get_dyn_func(*args):
else:
return globals()[func_name]
- except KeyError:
- raise Exception("No such function %s to call!" % func_name)
+ except KeyError as e:
+ raise Exception("No such function %s to call!" % func_name) from e
def get_hdd_size(device):
@@ -437,7 +441,7 @@ def get_hdd_size(device):
size_in_bytes, _ = subp.subp([BLKDEV_CMD, '--getsize64', device])
sector_size, _ = subp.subp([BLKDEV_CMD, '--getss', device])
except Exception as e:
- raise Exception("Failed to get %s size\n%s" % (device, e))
+ raise Exception("Failed to get %s size\n%s" % (device, e)) from e
return int(size_in_bytes) / int(sector_size)
@@ -455,8 +459,9 @@ def check_partition_mbr_layout(device, layout):
try:
out, _err = subp.subp(prt_cmd, data="%s\n" % layout)
except Exception as e:
- raise Exception("Error running partition command on %s\n%s" % (
- device, e))
+ raise Exception(
+ "Error running partition command on %s\n%s" % (device, e)
+ ) from e
found_layout = []
for line in out.splitlines():
@@ -485,8 +490,9 @@ def check_partition_gpt_layout(device, layout):
try:
out, _err = subp.subp(prt_cmd, update_env=LANG_C_ENV)
except Exception as e:
- raise Exception("Error running partition command on %s\n%s" % (
- device, e))
+ raise Exception(
+ "Error running partition command on %s\n%s" % (device, e)
+ ) from e
out_lines = iter(out.splitlines())
# Skip header. Output looks like:
@@ -657,8 +663,10 @@ def purge_disk(device):
try:
LOG.info("Purging filesystem on /dev/%s", d['name'])
subp.subp(wipefs_cmd)
- except Exception:
- raise Exception("Failed FS purge of /dev/%s" % d['name'])
+ except Exception as e:
+ raise Exception(
+ "Failed FS purge of /dev/%s" % d['name']
+ ) from e
purge_disk_ptable(device)
@@ -700,7 +708,9 @@ def exec_mkpart_mbr(device, layout):
try:
subp.subp(prt_cmd, data="%s\n" % layout)
except Exception as e:
- raise Exception("Failed to partition device %s\n%s" % (device, e))
+ raise Exception(
+ "Failed to partition device %s\n%s" % (device, e)
+ ) from e
read_parttbl(device)
@@ -997,6 +1007,6 @@ def mkfs(fs_cfg):
try:
subp.subp(fs_cmd, shell=shell)
except Exception as e:
- raise Exception("Failed to exec of '%s':\n%s" % (fs_cmd, e))
+ raise Exception("Failed to exec of '%s':\n%s" % (fs_cmd, e)) from e
# vi: ts=4 expandtab
diff --git a/cloudinit/config/cc_growpart.py b/cloudinit/config/cc_growpart.py
index c5d93f81..237c3d02 100644
--- a/cloudinit/config/cc_growpart.py
+++ b/cloudinit/config/cc_growpart.py
@@ -148,14 +148,14 @@ class ResizeGrowPart(object):
if e.exit_code != 1:
util.logexc(LOG, "Failed growpart --dry-run for (%s, %s)",
diskdev, partnum)
- raise ResizeFailedException(e)
+ raise ResizeFailedException(e) from e
return (before, before)
try:
subp.subp(["growpart", diskdev, partnum])
except subp.ProcessExecutionError as e:
util.logexc(LOG, "Failed: growpart %s %s", diskdev, partnum)
- raise ResizeFailedException(e)
+ raise ResizeFailedException(e) from e
return (before, get_size(partdev))
@@ -187,14 +187,14 @@ class ResizeGpart(object):
except subp.ProcessExecutionError as e:
if e.exit_code != 0:
util.logexc(LOG, "Failed: gpart recover %s", diskdev)
- raise ResizeFailedException(e)
+ raise ResizeFailedException(e) from e
before = get_size(partdev)
try:
subp.subp(["gpart", "resize", "-i", partnum, diskdev])
except subp.ProcessExecutionError as e:
util.logexc(LOG, "Failed: gpart resize -i %s %s", partnum, diskdev)
- raise ResizeFailedException(e)
+ raise ResizeFailedException(e) from e
# Since growing the FS requires a reboot, make sure we reboot
# first when this module has finished.
diff --git a/cloudinit/config/cc_power_state_change.py b/cloudinit/config/cc_power_state_change.py
index ab953a0d..6fcb8a7d 100644
--- a/cloudinit/config/cc_power_state_change.py
+++ b/cloudinit/config/cc_power_state_change.py
@@ -196,10 +196,11 @@ def load_power_state(cfg, distro_name):
try:
delay = convert_delay(delay, fmt=fmt, scale=scale)
- except ValueError:
+ except ValueError as e:
raise TypeError(
"power_state[delay] must be 'now' or '+m' (minutes)."
- " found '%s'." % delay)
+ " found '%s'." % delay
+ ) from e
args = command + [delay]
if message:
@@ -207,9 +208,10 @@ def load_power_state(cfg, distro_name):
try:
timeout = float(pstate.get('timeout', 30.0))
- except ValueError:
- raise ValueError("failed to convert timeout '%s' to float." %
- pstate['timeout'])
+ except ValueError as e:
+ raise ValueError(
+ "failed to convert timeout '%s' to float." % pstate['timeout']
+ ) from e
condition = pstate.get("condition", True)
if not isinstance(condition, (str, list, bool)):
diff --git a/cloudinit/config/cc_rsyslog.py b/cloudinit/config/cc_rsyslog.py
index 1354885a..2a2bc931 100644
--- a/cloudinit/config/cc_rsyslog.py
+++ b/cloudinit/config/cc_rsyslog.py
@@ -347,8 +347,10 @@ class SyslogRemotesLine(object):
if self.port:
try:
int(self.port)
- except ValueError:
- raise ValueError("port '%s' is not an integer" % self.port)
+ except ValueError as e:
+ raise ValueError(
+ "port '%s' is not an integer" % self.port
+ ) from e
if not self.addr:
raise ValueError("address is required")
diff --git a/cloudinit/config/cc_set_hostname.py b/cloudinit/config/cc_set_hostname.py
index c13020d8..1d23d80d 100644
--- a/cloudinit/config/cc_set_hostname.py
+++ b/cloudinit/config/cc_set_hostname.py
@@ -85,7 +85,7 @@ def handle(name, cfg, cloud, log, _args):
except Exception as e:
msg = "Failed to set the hostname to %s (%s)" % (fqdn, hostname)
util.logexc(log, msg)
- raise SetHostnameError("%s: %s" % (msg, e))
+ raise SetHostnameError("%s: %s" % (msg, e)) from e
write_json(prev_fn, {'hostname': hostname, 'fqdn': fqdn})
# vi: ts=4 expandtab
diff --git a/cloudinit/config/cc_ubuntu_advantage.py b/cloudinit/config/cc_ubuntu_advantage.py
index 35ded5db..d61dc655 100644
--- a/cloudinit/config/cc_ubuntu_advantage.py
+++ b/cloudinit/config/cc_ubuntu_advantage.py
@@ -115,7 +115,7 @@ def configure_ua(token=None, enable=None):
msg = 'Failure attaching Ubuntu Advantage:\n{error}'.format(
error=str(e))
util.logexc(LOG, msg)
- raise RuntimeError(msg)
+ raise RuntimeError(msg) from e
enable_errors = []
for service in enable:
try:
diff --git a/cloudinit/config/schema.py b/cloudinit/config/schema.py
index 2d8c7577..8a966aee 100644
--- a/cloudinit/config/schema.py
+++ b/cloudinit/config/schema.py
@@ -210,7 +210,7 @@ def validate_cloudconfig_file(config_path, schema, annotate=False):
error = SchemaValidationError(errors)
if annotate:
print(annotated_cloudconfig_file({}, content, error.schema_errors))
- raise error
+ raise error from e
try:
validate_cloudconfig_schema(
cloudconfig, schema, strict=True)
diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py
index effb4276..2537608f 100755
--- a/cloudinit/distros/__init__.py
+++ b/cloudinit/distros/__init__.py
@@ -607,10 +607,11 @@ class Distro(metaclass=abc.ABCMeta):
lock_tools = (['passwd', '-l', name], ['usermod', '--lock', name])
try:
cmd = next(tool for tool in lock_tools if subp.which(tool[0]))
- except StopIteration:
+ except StopIteration as e:
raise RuntimeError((
"Unable to lock user account '%s'. No tools available. "
- " Tried: %s.") % (name, [c[0] for c in lock_tools]))
+ " Tried: %s.") % (name, [c[0] for c in lock_tools])
+ ) from e
try:
subp.subp(cmd)
except Exception as e:
diff --git a/cloudinit/distros/arch.py b/cloudinit/distros/arch.py
index 038aa9ac..967be168 100644
--- a/cloudinit/distros/arch.py
+++ b/cloudinit/distros/arch.py
@@ -61,9 +61,9 @@ class Distro(distros.Distro):
def _write_network_config(self, netconfig):
try:
return self._supported_write_network_config(netconfig)
- except RendererNotFoundError:
+ except RendererNotFoundError as e:
# Fall back to old _write_network
- raise NotImplementedError
+ raise NotImplementedError from e
def _write_network(self, settings):
entries = net_util.translate_network(settings)
diff --git a/cloudinit/distros/parsers/resolv_conf.py b/cloudinit/distros/parsers/resolv_conf.py
index 299d54b5..62929d03 100644
--- a/cloudinit/distros/parsers/resolv_conf.py
+++ b/cloudinit/distros/parsers/resolv_conf.py
@@ -150,9 +150,10 @@ class ResolvConf(object):
tail = ''
try:
(cfg_opt, cfg_values) = head.split(None, 1)
- except (IndexError, ValueError):
- raise IOError("Incorrectly formatted resolv.conf line %s"
- % (i + 1))
+ except (IndexError, ValueError) as e:
+ raise IOError(
+ "Incorrectly formatted resolv.conf line %s" % (i + 1)
+ ) from e
if cfg_opt not in ['nameserver', 'domain',
'search', 'sortlist', 'options']:
raise IOError("Unexpected resolv.conf option %s" % (cfg_opt))
diff --git a/cloudinit/gpg.py b/cloudinit/gpg.py
index 72b5ac59..be0ca0ea 100644
--- a/cloudinit/gpg.py
+++ b/cloudinit/gpg.py
@@ -63,10 +63,11 @@ def recv_key(key, keyserver, retries=(1, 1)):
"Import failed with exit code %d, will try again in %ss",
error.exit_code, naplen)
time.sleep(naplen)
- except StopIteration:
+ except StopIteration as e:
raise ValueError(
("Failed to import key '%s' from keyserver '%s' "
- "after %d tries: %s") % (key, keyserver, trynum, error))
+ "after %d tries: %s") % (key, keyserver, trynum, error)
+ ) from e
def delete_key(key):
diff --git a/cloudinit/handlers/jinja_template.py b/cloudinit/handlers/jinja_template.py
index ce3accf6..aadfbf86 100644
--- a/cloudinit/handlers/jinja_template.py
+++ b/cloudinit/handlers/jinja_template.py
@@ -83,7 +83,8 @@ def render_jinja_payload_from_file(
if e.errno == EACCES:
raise RuntimeError(
'Cannot render jinja template vars. No read permission on'
- " '%s'. Try sudo" % instance_data_file)
+ " '%s'. Try sudo" % instance_data_file
+ ) from e
rendered_payload = render_jinja_payload(
payload, payload_fn, instance_data, debug)
diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py
index 322af77b..e233149a 100644
--- a/cloudinit/net/__init__.py
+++ b/cloudinit/net/__init__.py
@@ -506,7 +506,9 @@ def apply_network_config_names(netcfg, strict_present=True, strict_busy=True):
try:
_rename_interfaces(extract_physdevs(netcfg))
except RuntimeError as e:
- raise RuntimeError('Failed to apply network config names: %s' % e)
+ raise RuntimeError(
+ 'Failed to apply network config names: %s' % e
+ ) from e
def interface_has_own_mac(ifname, strict=False):
@@ -965,7 +967,8 @@ class EphemeralIPv4Network(object):
self.prefix = mask_to_net_prefix(prefix_or_mask)
except ValueError as e:
raise ValueError(
- 'Cannot setup network: {0}'.format(e))
+ 'Cannot setup network: {0}'.format(e)
+ ) from e
self.connectivity_url = connectivity_url
self.interface = interface
diff --git a/cloudinit/net/cmdline.py b/cloudinit/net/cmdline.py
index 7ca7262b..cc8dc17b 100755
--- a/cloudinit/net/cmdline.py
+++ b/cloudinit/net/cmdline.py
@@ -112,8 +112,8 @@ def _klibc_to_config_entry(content, mac_addrs=None):
data = util.load_shell_content(content)
try:
name = data['DEVICE'] if 'DEVICE' in data else data['DEVICE6']
- except KeyError:
- raise ValueError("no 'DEVICE' or 'DEVICE6' entry in data")
+ except KeyError as e:
+ raise ValueError("no 'DEVICE' or 'DEVICE6' entry in data") from e
# ipconfig on precise does not write PROTO
# IPv6 config gives us IPV6PROTO, not PROTO.
diff --git a/cloudinit/net/dhcp.py b/cloudinit/net/dhcp.py
index 9230cf7a..4394c68b 100644
--- a/cloudinit/net/dhcp.py
+++ b/cloudinit/net/dhcp.py
@@ -82,8 +82,8 @@ class EphemeralDHCPv4(object):
try:
leases = maybe_perform_dhcp_discovery(
self.iface, self.dhcp_log_func)
- except InvalidDHCPLeaseFileError:
- raise NoDHCPLeaseError()
+ except InvalidDHCPLeaseFileError as e:
+ raise NoDHCPLeaseError() from e
if not leases:
raise NoDHCPLeaseError()
self.lease = leases[-1]
diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py
index 7bfe8be0..b2f7d31e 100644
--- a/cloudinit/net/network_state.py
+++ b/cloudinit/net/network_state.py
@@ -297,9 +297,10 @@ class NetworkStateInterpreter(metaclass=CommandHandlerMeta):
command_type = command['type']
try:
handler = self.command_handlers[command_type]
- except KeyError:
- raise RuntimeError("No handler found for"
- " command '%s'" % command_type)
+ except KeyError as e:
+ raise RuntimeError(
+ "No handler found for command '%s'" % command_type
+ ) from e
try:
handler(self, command)
except InvalidCommand:
@@ -316,9 +317,10 @@ class NetworkStateInterpreter(metaclass=CommandHandlerMeta):
continue
try:
handler = self.command_handlers[command_type]
- except KeyError:
- raise RuntimeError("No handler found for"
- " command '%s'" % command_type)
+ except KeyError as e:
+ raise RuntimeError(
+ "No handler found for command '%s'" % command_type
+ ) from e
try:
handler(self, command)
self._v2_common(command)
@@ -914,9 +916,10 @@ def _normalize_route(route):
if metric:
try:
normal_route['metric'] = int(metric)
- except ValueError:
+ except ValueError as e:
raise TypeError(
- 'Route config metric {} is not an integer'.format(metric))
+ 'Route config metric {} is not an integer'.format(metric)
+ ) from e
return normal_route
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
index 86cc7c28..f3c6452b 100755
--- a/cloudinit/sources/DataSourceAzure.py
+++ b/cloudinit/sources/DataSourceAzure.py
@@ -1147,7 +1147,7 @@ def read_azure_ovf(contents):
except Exception as e:
error_str = "Invalid ovf-env.xml: %s" % e
report_diagnostic_event(error_str)
- raise BrokenAzureDataSource(error_str)
+ raise BrokenAzureDataSource(error_str) from e
results = find_child(dom.documentElement,
lambda n: n.localName == "ProvisioningSection")
diff --git a/cloudinit/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py
index 355b4e2f..1d09c12a 100644
--- a/cloudinit/sources/DataSourceEc2.py
+++ b/cloudinit/sources/DataSourceEc2.py
@@ -617,9 +617,11 @@ def parse_strict_mode(cfgval):
if sleep:
try:
sleep = int(sleep)
- except ValueError:
- raise ValueError("Invalid sleep '%s' in strict_id setting '%s': "
- "not an integer" % (sleep, cfgval))
+ except ValueError as e:
+ raise ValueError(
+ "Invalid sleep '%s' in strict_id setting '%s': not an integer"
+ % (sleep, cfgval)
+ ) from e
else:
sleep = None
diff --git a/cloudinit/sources/DataSourceIBMCloud.py b/cloudinit/sources/DataSourceIBMCloud.py
index d2aa9a58..8d196185 100644
--- a/cloudinit/sources/DataSourceIBMCloud.py
+++ b/cloudinit/sources/DataSourceIBMCloud.py
@@ -303,7 +303,8 @@ def read_md():
except sources.BrokenMetadata as e:
raise RuntimeError(
"Failed reading IBM config disk (platform=%s path=%s): %s" %
- (platform, path, e))
+ (platform, path, e)
+ ) from e
ret.update(results)
return ret
diff --git a/cloudinit/sources/DataSourceMAAS.py b/cloudinit/sources/DataSourceMAAS.py
index c80f70c2..9156925f 100644
--- a/cloudinit/sources/DataSourceMAAS.py
+++ b/cloudinit/sources/DataSourceMAAS.py
@@ -226,7 +226,8 @@ def read_maas_seed_url(seed_url, read_file_or_url=None, timeout=None,
except url_helper.UrlError as e:
if e.code == 404 and not optional:
raise MAASSeedDirMalformed(
- "Missing required %s: %s" % (path, e))
+ "Missing required %s: %s" % (path, e)
+ ) from e
elif e.code != 404:
raise e
diff --git a/cloudinit/sources/DataSourceOpenNebula.py b/cloudinit/sources/DataSourceOpenNebula.py
index 12b1f94f..45481938 100644
--- a/cloudinit/sources/DataSourceOpenNebula.py
+++ b/cloudinit/sources/DataSourceOpenNebula.py
@@ -399,18 +399,23 @@ def read_context_disk_dir(source_dir, distro, asuser=None):
if asuser is not None:
try:
pwd.getpwnam(asuser)
- except KeyError:
+ except KeyError as e:
raise BrokenContextDiskDir(
"configured user '{user}' does not exist".format(
- user=asuser))
+ user=asuser)
+ ) from e
try:
path = os.path.join(source_dir, 'context.sh')
content = util.load_file(path)
context = parse_shell_config(content, asuser=asuser)
except subp.ProcessExecutionError as e:
- raise BrokenContextDiskDir("Error processing context.sh: %s" % (e))
+ raise BrokenContextDiskDir(
+ "Error processing context.sh: %s" % (e)
+ ) from e
except IOError as e:
- raise NonContextDiskDir("Error reading context.sh: %s" % (e))
+ raise NonContextDiskDir(
+ "Error reading context.sh: %s" % (e)
+ ) from e
else:
raise NonContextDiskDir("Missing context.sh")
diff --git a/cloudinit/sources/DataSourceOpenStack.py b/cloudinit/sources/DataSourceOpenStack.py
index bf539091..d4b43f44 100644
--- a/cloudinit/sources/DataSourceOpenStack.py
+++ b/cloudinit/sources/DataSourceOpenStack.py
@@ -194,10 +194,10 @@ class DataSourceOpenStack(openstack.SourceMixin, sources.DataSource):
'timeout': url_params.timeout_seconds})
except openstack.NonReadable as e:
raise sources.InvalidMetaDataException(str(e))
- except (openstack.BrokenMetadata, IOError):
+ except (openstack.BrokenMetadata, IOError) as e:
msg = 'Broken metadata address {addr}'.format(
addr=self.metadata_address)
- raise sources.InvalidMetaDataException(msg)
+ raise sources.InvalidMetaDataException(msg) from e
return result
diff --git a/cloudinit/sources/DataSourceSmartOS.py b/cloudinit/sources/DataSourceSmartOS.py
index 843b3a2a..f1f903bc 100644
--- a/cloudinit/sources/DataSourceSmartOS.py
+++ b/cloudinit/sources/DataSourceSmartOS.py
@@ -413,7 +413,9 @@ class JoyentMetadataClient(object):
response.append(byte)
except OSError as exc:
if exc.errno == errno.EAGAIN:
- raise JoyentMetadataTimeoutException(msg % as_ascii())
+ raise JoyentMetadataTimeoutException(
+ msg % as_ascii()
+ ) from exc
raise
def _write(self, msg):
diff --git a/cloudinit/sources/helpers/azure.py b/cloudinit/sources/helpers/azure.py
index 6156c75b..b968a96f 100755
--- a/cloudinit/sources/helpers/azure.py
+++ b/cloudinit/sources/helpers/azure.py
@@ -98,8 +98,10 @@ def get_boot_telemetry():
LOG.debug("Collecting boot telemetry")
try:
kernel_start = float(time.time()) - float(util.uptime())
- except ValueError:
- raise RuntimeError("Failed to determine kernel start timestamp")
+ except ValueError as e:
+ raise RuntimeError(
+ "Failed to determine kernel start timestamp"
+ ) from e
try:
out, _ = subp.subp(['/bin/systemctl',
@@ -116,12 +118,13 @@ def get_boot_telemetry():
user_start = kernel_start + (float(tsm) / 1000000)
except subp.ProcessExecutionError as e:
- raise RuntimeError("Failed to get UserspaceTimestampMonotonic: %s"
- % e)
+ raise RuntimeError(
+ "Failed to get UserspaceTimestampMonotonic: %s" % e
+ ) from e
except ValueError as e:
- raise RuntimeError("Failed to parse "
- "UserspaceTimestampMonotonic from systemd: %s"
- % e)
+ raise RuntimeError(
+ "Failed to parse UserspaceTimestampMonotonic from systemd: %s" % e
+ ) from e
try:
out, _ = subp.subp(['/bin/systemctl', 'show',
@@ -137,12 +140,14 @@ def get_boot_telemetry():
cloudinit_activation = kernel_start + (float(tsm) / 1000000)
except subp.ProcessExecutionError as e:
- raise RuntimeError("Failed to get InactiveExitTimestampMonotonic: %s"
- % e)
+ raise RuntimeError(
+ "Failed to get InactiveExitTimestampMonotonic: %s" % e
+ ) from e
except ValueError as e:
- raise RuntimeError("Failed to parse "
- "InactiveExitTimestampMonotonic from systemd: %s"
- % e)
+ raise RuntimeError(
+ "Failed to parse InactiveExitTimestampMonotonic from systemd: %s"
+ % e
+ ) from e
evt = events.ReportingEvent(
BOOT_EVENT_TYPE, 'boot-telemetry',
@@ -642,9 +647,10 @@ class WALinuxAgentShim:
try:
name = os.path.basename(hook_file).replace('.json', '')
dhcp_options[name] = json.loads(util.load_file((hook_file)))
- except ValueError:
+ except ValueError as e:
raise ValueError(
- '{_file} is not valid JSON data'.format(_file=hook_file))
+ '{_file} is not valid JSON data'.format(_file=hook_file)
+ ) from e
return dhcp_options
@staticmethod
diff --git a/cloudinit/sources/helpers/netlink.py b/cloudinit/sources/helpers/netlink.py
index a74a3588..c2ad587b 100644
--- a/cloudinit/sources/helpers/netlink.py
+++ b/cloudinit/sources/helpers/netlink.py
@@ -74,7 +74,7 @@ def create_bound_netlink_socket():
netlink_socket.setblocking(0)
except socket.error as e:
msg = "Exception during netlink socket create: %s" % e
- raise NetlinkCreateSocketError(msg)
+ raise NetlinkCreateSocketError(msg) from e
LOG.debug("Created netlink socket")
return netlink_socket
diff --git a/cloudinit/sources/helpers/openstack.py b/cloudinit/sources/helpers/openstack.py
index 1050efb0..65e020c5 100644
--- a/cloudinit/sources/helpers/openstack.py
+++ b/cloudinit/sources/helpers/openstack.py
@@ -280,8 +280,9 @@ class BaseReader(metaclass=abc.ABCMeta):
try:
data = translator(data)
except Exception as e:
- raise BrokenMetadata("Failed to process "
- "path %s: %s" % (path, e))
+ raise BrokenMetadata(
+ "Failed to process path %s: %s" % (path, e)
+ ) from e
if found:
results[name] = data
@@ -291,8 +292,9 @@ class BaseReader(metaclass=abc.ABCMeta):
try:
metadata['random_seed'] = base64.b64decode(random_seed)
except (ValueError, TypeError) as e:
- raise BrokenMetadata("Badly formatted metadata"
- " random_seed entry: %s" % e)
+ raise BrokenMetadata(
+ "Badly formatted metadata random_seed entry: %s" % e
+ ) from e
# load any files that were provided
files = {}
@@ -304,8 +306,9 @@ class BaseReader(metaclass=abc.ABCMeta):
try:
files[path] = self._read_content_path(item)
except Exception as e:
- raise BrokenMetadata("Failed to read provided "
- "file %s: %s" % (path, e))
+ raise BrokenMetadata(
+ "Failed to read provided file %s: %s" % (path, e)
+ ) from e
results['files'] = files
# The 'network_config' item in metadata is a content pointer
@@ -317,8 +320,9 @@ class BaseReader(metaclass=abc.ABCMeta):
content = self._read_content_path(net_item, decode=True)
results['network_config'] = content
except IOError as e:
- raise BrokenMetadata("Failed to read network"
- " configuration: %s" % (e))
+ raise BrokenMetadata(
+ "Failed to read network configuration: %s" % (e)
+ ) from e
# To openstack, user can specify meta ('nova boot --meta=key=value')
# and those will appear under metadata['meta'].
@@ -370,8 +374,9 @@ class ConfigDriveReader(BaseReader):
try:
return util.load_json(self._path_read(path))
except Exception as e:
- raise BrokenMetadata("Failed to process "
- "path %s: %s" % (path, e))
+ raise BrokenMetadata(
+ "Failed to process path %s: %s" % (path, e)
+ ) from e
def read_v1(self):
"""Reads a version 1 formatted location.
@@ -395,16 +400,17 @@ class ConfigDriveReader(BaseReader):
path = found[name]
try:
contents = self._path_read(path)
- except IOError:
- raise BrokenMetadata("Failed to read: %s" % path)
+ except IOError as e:
+ raise BrokenMetadata("Failed to read: %s" % path) from e
try:
# Disable not-callable pylint check; pylint isn't able to
# determine that every member of FILES_V1 has a callable in
# the appropriate position
md[key] = translator(contents) # pylint: disable=E1102
except Exception as e:
- raise BrokenMetadata("Failed to process "
- "path %s: %s" % (path, e))
+ raise BrokenMetadata(
+ "Failed to process path %s: %s" % (path, e)
+ ) from e
else:
md[key] = copy.deepcopy(default)
diff --git a/cloudinit/subp.py b/cloudinit/subp.py
index 804ef3ca..3e4efa42 100644
--- a/cloudinit/subp.py
+++ b/cloudinit/subp.py
@@ -262,7 +262,8 @@ def subp(args, data=None, rcs=None, env=None, capture=True,
raise ProcessExecutionError(
cmd=args, reason=e, errno=e.errno,
stdout="-" if decode else b"-",
- stderr="-" if decode else b"-")
+ stderr="-" if decode else b"-"
+ ) from e
finally:
if devnull_fp:
devnull_fp.close()
diff --git a/cloudinit/url_helper.py b/cloudinit/url_helper.py
index f3c0cf9c..caa88435 100644
--- a/cloudinit/url_helper.py
+++ b/cloudinit/url_helper.py
@@ -95,7 +95,7 @@ def read_file_or_url(url, **kwargs):
code = e.errno
if e.errno == ENOENT:
code = NOT_FOUND
- raise UrlError(cause=e, code=code, headers=None, url=url)
+ raise UrlError(cause=e, code=code, headers=None, url=url) from e
return FileResponse(file_path, contents=contents)
else:
return readurl(url, **kwargs)
@@ -575,8 +575,8 @@ def oauth_headers(url, consumer_key, token_key, token_secret, consumer_secret,
timestamp=None):
try:
import oauthlib.oauth1 as oauth1
- except ImportError:
- raise NotImplementedError('oauth support is not available')
+ except ImportError as e:
+ raise NotImplementedError('oauth support is not available') from e
if timestamp:
timestamp = str(timestamp)
diff --git a/cloudinit/util.py b/cloudinit/util.py
index dd263803..cf9e349f 100644
--- a/cloudinit/util.py
+++ b/cloudinit/util.py
@@ -359,7 +359,7 @@ def decomp_gzip(data, quiet=True, decode=True):
if quiet:
return data
else:
- raise DecompressionError(str(e))
+ raise DecompressionError(str(e)) from e
def extract_usergroup(ug_pair):
@@ -1363,7 +1363,7 @@ def chownbyname(fname, user=None, group=None):
if group:
gid = grp.getgrnam(group).gr_gid
except KeyError as e:
- raise OSError("Unknown user or group: %s" % (e))
+ raise OSError("Unknown user or group: %s" % (e)) from e
chownbyid(fname, uid, gid)
@@ -2387,8 +2387,8 @@ def human2bytes(size):
try:
num = float(num)
- except ValueError:
- raise ValueError("'%s' is not valid input." % size_in)
+ except ValueError as e:
+ raise ValueError("'%s' is not valid input." % size_in) from e
if num < 0:
raise ValueError("'%s': cannot be negative" % size_in)
diff --git a/tests/cloud_tests/platforms/azurecloud/instance.py b/tests/cloud_tests/platforms/azurecloud/instance.py
index a136cf0d..eedbaae8 100644
--- a/tests/cloud_tests/platforms/azurecloud/instance.py
+++ b/tests/cloud_tests/platforms/azurecloud/instance.py
@@ -134,9 +134,10 @@ class AzureCloudInstance(Instance):
self.vm_name, vm_params)
LOG.debug('creating instance %s from image_id=%s', self.vm_name,
self.image_id)
- except CloudError:
- raise RuntimeError('failed creating instance:\n{}'.format(
- traceback.format_exc()))
+ except CloudError as e:
+ raise RuntimeError(
+ 'failed creating instance:\n{}'.format(traceback.format_exc())
+ ) from e
if wait:
self.instance.wait()
diff --git a/tests/cloud_tests/platforms/azurecloud/platform.py b/tests/cloud_tests/platforms/azurecloud/platform.py
index cb62a74b..a664f612 100644
--- a/tests/cloud_tests/platforms/azurecloud/platform.py
+++ b/tests/cloud_tests/platforms/azurecloud/platform.py
@@ -59,9 +59,12 @@ class AzureCloudPlatform(Platform):
self.vnet = self._create_vnet()
self.subnet = self._create_subnet()
self.nic = self._create_nic()
- except CloudError:
- raise RuntimeError('failed creating a resource:\n{}'.format(
- traceback.format_exc()))
+ except CloudError as e:
+ raise RuntimeError(
+ 'failed creating a resource:\n{}'.format(
+ traceback.format_exc()
+ )
+ ) from e
def create_instance(self, properties, config, features,
image_id, user_data=None):
@@ -105,8 +108,10 @@ class AzureCloudPlatform(Platform):
if image_id.find('__') > 0:
image_id = image_id.split('__')[1]
LOG.debug('image_id shortened to %s', image_id)
- except KeyError:
- raise RuntimeError('no images found for %s' % img_conf['release'])
+ except KeyError as e:
+ raise RuntimeError(
+ 'no images found for %s' % img_conf['release']
+ ) from e
return AzureCloudImage(self, img_conf, image_id)
@@ -140,9 +145,11 @@ class AzureCloudPlatform(Platform):
secret=azure_creds['clientSecret'],
tenant=azure_creds['tenantId'])
return credentials, subscription_id
- except KeyError:
- raise RuntimeError('Please configure Azure service principal'
- ' credentials in %s' % cred_file)
+ except KeyError as e:
+ raise RuntimeError(
+ 'Please configure Azure service principal'
+ ' credentials in %s' % cred_file
+ ) from e
def _create_resource_group(self):
"""Create resource group"""
diff --git a/tests/cloud_tests/platforms/ec2/instance.py b/tests/cloud_tests/platforms/ec2/instance.py
index ab6037b1..d2e84047 100644
--- a/tests/cloud_tests/platforms/ec2/instance.py
+++ b/tests/cloud_tests/platforms/ec2/instance.py
@@ -49,11 +49,11 @@ class EC2Instance(Instance):
# OutputBytes comes from platform._decode_console_output_as_bytes
response = self.instance.console_output()
return response['OutputBytes']
- except KeyError:
+ except KeyError as e:
if 'Output' in response:
msg = ("'OutputBytes' did not exist in console_output() but "
"'Output' did: %s..." % response['Output'][0:128])
- raise util.PlatformError('console_log', msg)
+ raise util.PlatformError('console_log', msg) from e
return ('No Console Output [%s]' % self.instance).encode()
def destroy(self):
diff --git a/tests/cloud_tests/platforms/ec2/platform.py b/tests/cloud_tests/platforms/ec2/platform.py
index 7a3d0fe0..b61a2ffb 100644
--- a/tests/cloud_tests/platforms/ec2/platform.py
+++ b/tests/cloud_tests/platforms/ec2/platform.py
@@ -35,12 +35,14 @@ class EC2Platform(Platform):
self.ec2_resource = b3session.resource('ec2')
self.ec2_region = b3session.region_name
self.key_name = self._upload_public_key(config)
- except botocore.exceptions.NoRegionError:
+ except botocore.exceptions.NoRegionError as e:
raise RuntimeError(
- 'Please configure default region in $HOME/.aws/config')
- except botocore.exceptions.NoCredentialsError:
+ 'Please configure default region in $HOME/.aws/config'
+ ) from e
+ except botocore.exceptions.NoCredentialsError as e:
raise RuntimeError(
- 'Please configure ec2 credentials in $HOME/.aws/credentials')
+ 'Please configure ec2 credentials in $HOME/.aws/credentials'
+ ) from e
self.vpc = self._create_vpc()
self.internet_gateway = self._create_internet_gateway()
@@ -125,8 +127,10 @@ class EC2Platform(Platform):
try:
image_ami = image['id']
- except KeyError:
- raise RuntimeError('No images found for %s!' % img_conf['release'])
+ except KeyError as e:
+ raise RuntimeError(
+ 'No images found for %s!' % img_conf['release']
+ ) from e
LOG.debug('found image: %s', image_ami)
image = EC2Image(self, img_conf, image_ami)
@@ -195,7 +199,7 @@ class EC2Platform(Platform):
CidrBlock=self.ipv4_cidr,
AmazonProvidedIpv6CidrBlock=True)
except botocore.exceptions.ClientError as e:
- raise RuntimeError(e)
+ raise RuntimeError(e) from e
vpc.wait_until_available()
self._tag_resource(vpc)
diff --git a/tests/cloud_tests/platforms/lxd/instance.py b/tests/cloud_tests/platforms/lxd/instance.py
index b27b9848..2b973a08 100644
--- a/tests/cloud_tests/platforms/lxd/instance.py
+++ b/tests/cloud_tests/platforms/lxd/instance.py
@@ -175,7 +175,8 @@ class LXDInstance(Instance):
raise PlatformError(
"console log",
"Console log failed [%d]: stdout=%s stderr=%s" % (
- e.exit_code, e.stdout, e.stderr))
+ e.exit_code, e.stdout, e.stderr)
+ ) from e
def reboot(self, wait=True):
"""Reboot instance."""
diff --git a/tests/cloud_tests/platforms/platforms.py b/tests/cloud_tests/platforms/platforms.py
index 58f65e52..ac3b6563 100644
--- a/tests/cloud_tests/platforms/platforms.py
+++ b/tests/cloud_tests/platforms/platforms.py
@@ -74,8 +74,10 @@ class Platform(object):
try:
return tmirror.json_entries[0]
- except IndexError:
- raise RuntimeError('no images found with filter: %s' % img_filter)
+ except IndexError as e:
+ raise RuntimeError(
+ 'no images found with filter: %s' % img_filter
+ ) from e
class FilterMirror(mirrors.BasicMirrorWriter):
diff --git a/tests/cloud_tests/testcases/__init__.py b/tests/cloud_tests/testcases/__init__.py
index e8c371ca..bb9785d3 100644
--- a/tests/cloud_tests/testcases/__init__.py
+++ b/tests/cloud_tests/testcases/__init__.py
@@ -21,8 +21,10 @@ def discover_test(test_name):
config.name_sanitize(test_name))
try:
testmod = importlib.import_module(testmod_name)
- except NameError:
- raise ValueError('no test verifier found at: {}'.format(testmod_name))
+ except NameError as e:
+ raise ValueError(
+ 'no test verifier found at: {}'.format(testmod_name)
+ ) from e
found = [mod for name, mod in inspect.getmembers(testmod)
if (inspect.isclass(mod)
diff --git a/tools/mock-meta.py b/tools/mock-meta.py
index a58e0260..9dd067b9 100755
--- a/tools/mock-meta.py
+++ b/tools/mock-meta.py
@@ -258,12 +258,14 @@ class MetaDataHandler(object):
try:
key_id = int(mybe_key)
key_name = key_ids[key_id]
- except ValueError:
- raise WebException(hclient.BAD_REQUEST,
- "%s: not an integer" % mybe_key)
- except IndexError:
- raise WebException(hclient.NOT_FOUND,
- "Unknown key id %r" % mybe_key)
+ except ValueError as e:
+ raise WebException(
+ hclient.BAD_REQUEST, "%s: not an integer" % mybe_key
+ ) from e
+ except IndexError as e:
+ raise WebException(
+ hclient.NOT_FOUND, "Unknown key id %r" % mybe_key
+ ) from e
# Extract the possible sub-params
result = traverse(nparams[1:], {
"openssh-key": "\n".join(avail_keys[key_name]),
diff --git a/tox.ini b/tox.ini
index f619dbf5..a92c63e0 100644
--- a/tox.ini
+++ b/tox.ini
@@ -23,7 +23,7 @@ setenv =
basepython = python3
deps =
# requirements
- pylint==2.5.3
+ pylint==2.6.0
# test-requirements because unit tests are now present in cloudinit tree
-r{toxinidir}/test-requirements.txt
-r{toxinidir}/integration-requirements.txt