From 547f95c315192573bc2ca73240deb55ba6c033f9 Mon Sep 17 00:00:00 2001 From: Brett Holman Date: Mon, 22 Apr 2024 21:02:05 -0600 Subject: [PATCH] chore(IOError): Update IOError to OSError In Python 3.3+, IOError is an alias of OSError[1]. Some call sites use one or the other or both. Standardize on the OSError. [1] https://docs.python.org/3/library/exceptions.html#IOError --- cloudinit/apport.py | 2 +- cloudinit/cmd/cloud_id.py | 2 +- cloudinit/cmd/devel/render.py | 2 +- cloudinit/cmd/query.py | 17 ++++++++--------- cloudinit/config/cc_apt_configure.py | 4 ++-- cloudinit/config/cc_mcollective.py | 4 ++-- cloudinit/config/cc_mounts.py | 2 +- cloudinit/config/cc_power_state_change.py | 6 +++--- cloudinit/config/cc_seed_random.py | 2 +- cloudinit/config/schema.py | 4 ++-- cloudinit/distros/__init__.py | 16 ++++++++-------- cloudinit/distros/alpine.py | 4 ++-- cloudinit/distros/arch.py | 4 ++-- cloudinit/distros/debian.py | 4 ++-- cloudinit/distros/freebsd.py | 2 +- cloudinit/distros/gentoo.py | 4 ++-- cloudinit/distros/opensuse.py | 4 ++-- cloudinit/distros/parsers/hostname.py | 2 +- cloudinit/distros/parsers/resolv_conf.py | 4 ++-- cloudinit/distros/rhel_util.py | 2 +- cloudinit/helpers.py | 4 ++-- cloudinit/log.py | 4 ++-- cloudinit/net/bsd.py | 2 +- cloudinit/net/cmdline.py | 2 +- cloudinit/reporting/handlers.py | 6 +++--- cloudinit/sources/DataSourceAltCloud.py | 6 +++--- cloudinit/sources/DataSourceAzure.py | 2 +- cloudinit/sources/DataSourceBigstep.py | 2 +- cloudinit/sources/DataSourceConfigDrive.py | 4 ++-- cloudinit/sources/DataSourceIBMCloud.py | 2 +- cloudinit/sources/DataSourceOpenNebula.py | 2 +- cloudinit/sources/DataSourceOpenStack.py | 6 +++--- cloudinit/sources/DataSourceSmartOS.py | 2 +- cloudinit/sources/DataSourceWSL.py | 12 ++++++------ cloudinit/sources/__init__.py | 2 +- cloudinit/sources/helpers/openstack.py | 6 +++--- cloudinit/ssh_util.py | 6 +++--- cloudinit/stages.py | 2 +- cloudinit/subp.py | 4 ++-- cloudinit/url_helper.py | 6 +++--- cloudinit/user_data.py | 2 +- cloudinit/util.py | 14 +++++++------- tests/integration_tests/instances.py | 2 +- tests/unittests/cmd/test_query.py | 2 +- tests/unittests/config/test_cc_seed_random.py | 2 +- tests/unittests/config/test_cc_yum_add_repo.py | 2 +- .../unittests/config/test_cc_zypper_add_repo.py | 2 +- tests/unittests/config/test_schema.py | 4 ++-- tests/unittests/net/test_init.py | 5 ++--- tests/unittests/sources/test_altcloud.py | 4 ++-- tests/unittests/sources/test_wsl.py | 4 ++-- tests/unittests/test_merging.py | 4 ++-- tests/unittests/test_ssh_util.py | 2 +- tests/unittests/test_util.py | 4 ++-- 54 files changed, 112 insertions(+), 114 deletions(-) diff --git a/cloudinit/apport.py b/cloudinit/apport.py index f7d83e2b3198..505219fbc86c 100644 --- a/cloudinit/apport.py +++ b/cloudinit/apport.py @@ -128,7 +128,7 @@ def attach_cloud_info(report, ui=None): instance_data = json.load(file) assert instance_data.get("v1", {}).get("cloud_name") return # Valid instance-data means generic-hooks will report - except (IOError, json.decoder.JSONDecodeError, AssertionError): + except (OSError, json.decoder.JSONDecodeError, AssertionError): pass # No valid /run/cloud/instance-data.json on system. Prompt for cloud. diff --git a/cloudinit/cmd/cloud_id.py b/cloudinit/cmd/cloud_id.py index 4a856fe28b55..7943c693ee78 100644 --- a/cloudinit/cmd/cloud_id.py +++ b/cloudinit/cmd/cloud_id.py @@ -76,7 +76,7 @@ def handle_args(name, args): try: with open(args.instance_data) as file: instance_data = json.load(file) - except IOError: + except OSError: return error( "File not found '%s'. Provide a path to instance data json file" " using --instance-data" % args.instance_data diff --git a/cloudinit/cmd/devel/render.py b/cloudinit/cmd/devel/render.py index 152b7768197f..7c556a67a5e6 100755 --- a/cloudinit/cmd/devel/render.py +++ b/cloudinit/cmd/devel/render.py @@ -86,7 +86,7 @@ def render_template(user_data_path, instance_data_path=None, debug=False): try: with open(user_data_path) as stream: user_data = stream.read() - except IOError: + except OSError: LOG.error("Missing user-data file: %s", user_data_path) return 1 try: diff --git a/cloudinit/cmd/query.py b/cloudinit/cmd/query.py index cf85003bb945..e9132f458b9b 100644 --- a/cloudinit/cmd/query.py +++ b/cloudinit/cmd/query.py @@ -19,7 +19,6 @@ import logging import os import sys -from errno import EACCES from cloudinit import atomic_helper, util from cloudinit.cmd.devel import read_cfg_paths @@ -147,7 +146,7 @@ def _read_instance_data(instance_data, user_data, vendor_data) -> dict: Non-root users will have redacted INSTANCE_JSON_FILE content and redacted vendordata and userdata values. - :raise: IOError/OSError on absence of instance-data.json file or invalid + :raise: OSError on absence of instance-data.json file or invalid access perms. """ uid = os.getuid() @@ -181,11 +180,11 @@ def _read_instance_data(instance_data, user_data, vendor_data) -> dict: try: instance_json = util.load_text_file(instance_data_fn) - except (IOError, OSError) as e: - if e.errno == EACCES: - LOG.error("No read permission on '%s'. Try sudo", instance_data_fn) - else: - LOG.error("Missing instance-data file: %s", instance_data_fn) + except PermissionError: + LOG.error("No read permission on '%s'. Try sudo", instance_data_fn) + raise + except OSError: + LOG.error("Missing instance-data file: %s", instance_data_fn) raise instance_data = util.load_json(instance_json) @@ -193,7 +192,7 @@ def _read_instance_data(instance_data, user_data, vendor_data) -> dict: combined_cloud_config = util.load_json( util.load_text_file(combined_cloud_config_fn) ) - except (IOError, OSError): + except OSError: # File will not yet be present in init-local stage. # It's created in `init` when vendor-data and user-data are processed. combined_cloud_config = None @@ -274,7 +273,7 @@ def handle_args(name, args): instance_data = _read_instance_data( args.instance_data, args.user_data, args.vendor_data ) - except (IOError, OSError): + except OSError: return 1 if args.format: payload = "## template: jinja\n{fmt}".format(fmt=args.format) diff --git a/cloudinit/config/cc_apt_configure.py b/cloudinit/config/cc_apt_configure.py index 99a8f556c4d3..46181bb56e01 100644 --- a/cloudinit/config/cc_apt_configure.py +++ b/cloudinit/config/cc_apt_configure.py @@ -268,7 +268,7 @@ def apply_apt(cfg, cloud, gpg): try: apply_apt_config(cfg, APT_PROXY_FN, APT_CONFIG_FN) - except (IOError, OSError): + except OSError: LOG.exception("Failed to apply proxy or apt config info:") # Process 'apt_source -> sources {dict}' @@ -852,7 +852,7 @@ def add_apt_sources( omode = "w" util.write_file(sourcefn, contents, omode=omode) - except IOError as detail: + except OSError as detail: LOG.exception("failed write to file %s: %s", sourcefn, detail) raise diff --git a/cloudinit/config/cc_mcollective.py b/cloudinit/config/cc_mcollective.py index e5d0145b8064..f17f1823b39a 100644 --- a/cloudinit/config/cc_mcollective.py +++ b/cloudinit/config/cc_mcollective.py @@ -100,7 +100,7 @@ def configure( try: old_contents = util.load_binary_file(server_cfg, quiet=False) mcollective_config = ConfigObj(io.BytesIO(old_contents)) - except IOError as e: + except OSError as e: if e.errno != errno.ENOENT: raise else: @@ -137,7 +137,7 @@ def configure( # We got all our config as wanted we'll copy # the previous server.cfg and overwrite the old with our new one util.copy(server_cfg, "%s.old" % (server_cfg)) - except IOError as e: + except OSError as e: if e.errno == errno.ENOENT: # Doesn't exist to copy... pass diff --git a/cloudinit/config/cc_mounts.py b/cloudinit/config/cc_mounts.py index 84445e737ced..17dfbce1c458 100644 --- a/cloudinit/config/cc_mounts.py +++ b/cloudinit/config/cc_mounts.py @@ -349,7 +349,7 @@ def setup_swapfile(fname, size=None, maxsize=None): if str(size).lower() == "auto": try: memsize = util.read_meminfo()["total"] - except IOError: + except OSError: LOG.debug("Not creating swap: failed to read meminfo") return diff --git a/cloudinit/config/cc_power_state_change.py b/cloudinit/config/cc_power_state_change.py index 4b5d49978419..401d18f14924 100644 --- a/cloudinit/config/cc_power_state_change.py +++ b/cloudinit/config/cc_power_state_change.py @@ -96,7 +96,7 @@ def givecmdline(pid): return m.group(2) else: return util.load_text_file("/proc/%s/cmdline" % pid) - except IOError: + except OSError: return None @@ -242,11 +242,11 @@ def fatal(msg): msg = "cmdline changed for %s [now: %s]" % (pid, cmdline) break - except IOError as ioerr: + except OSError as ioerr: if ioerr.errno in known_errnos: msg = "pidfile gone [%d]" % ioerr.errno else: - fatal("IOError during wait: %s" % ioerr) + fatal("OSError during wait: %s" % ioerr) break except Exception as e: diff --git a/cloudinit/config/cc_seed_random.py b/cloudinit/config/cc_seed_random.py index 3e8b8267bb52..0f936e41b8b9 100644 --- a/cloudinit/config/cc_seed_random.py +++ b/cloudinit/config/cc_seed_random.py @@ -86,7 +86,7 @@ def _decode(data, encoding=None): elif encoding.lower() in ["gzip", "gz"]: return util.decomp_gzip(data, quiet=False, decode=None) else: - raise IOError("Unknown random_seed encoding: %s" % (encoding)) + raise OSError("Unknown random_seed encoding: %s" % (encoding)) def handle_random_seed_command(command, required, update_env): diff --git a/cloudinit/config/schema.py b/cloudinit/config/schema.py index abfab98a1d57..3a6e5651cb0c 100644 --- a/cloudinit/config/schema.py +++ b/cloudinit/config/schema.py @@ -1582,7 +1582,7 @@ def get_schema(schema_type: SchemaType = SchemaType.CLOUD_CONFIG) -> dict: full_schema = None try: full_schema = json.loads(load_text_file(schema_file)) - except (IOError, OSError): + except OSError: LOG.warning( "Skipping %s schema validation. No JSON schema file found %s.", schema_type.value, @@ -1722,7 +1722,7 @@ def get_processed_or_fallback_path( try: paths = read_cfg_paths(fetch_existing_datasource="trust") - except (IOError, OSError) as e: + except OSError as e: if e.errno == EACCES: LOG.debug( "Using default instance-data/user-data paths for non-root user" diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py index fe8735321244..bd32f5695ef1 100644 --- a/cloudinit/distros/__init__.py +++ b/cloudinit/distros/__init__.py @@ -367,7 +367,7 @@ def _write_network_state(self, network_state, renderer: Renderer): def _find_tz_file(self, tz): tz_file = os.path.join(self.tz_zone_dir, str(tz)) if not os.path.isfile(tz_file): - raise IOError( + raise OSError( "Invalid timezone %s, no file found at %s" % (tz, tz_file) ) return tz_file @@ -583,7 +583,7 @@ def update_hostname(self, hostname, fqdn, prev_hostname_fn): for fn in update_files: try: self._write_hostname(hostname, fn) - except IOError: + except OSError: util.logexc( LOG, "Failed to write hostname %s to %s", hostname, fn ) @@ -998,14 +998,14 @@ def write_doas_rules(self, user, rules, doas_file=None): contents = [util.make_header(), content] try: util.write_file(doas_file, "\n".join(contents), mode=0o440) - except IOError as e: + except OSError as e: util.logexc(LOG, "Failed to write doas file %s", doas_file) raise e else: if content not in util.load_text_file(doas_file): try: util.append_file(doas_file, content) - except IOError as e: + except OSError as e: util.logexc( LOG, "Failed to append to doas file %s", doas_file ) @@ -1055,7 +1055,7 @@ def ensure_sudo_dir(self, path, sudo_base="/etc/sudoers"): sudoers_contents = "\n".join(lines) util.append_file(sudo_base, sudoers_contents) LOG.debug("Added '#includedir %s' to %s", path, sudo_base) - except IOError as e: + except OSError as e: util.logexc(LOG, "Failed to write %s", sudo_base) raise e util.ensure_dir(path, 0o750) @@ -1088,14 +1088,14 @@ def write_sudo_rules(self, user, rules, sudo_file=None): ] try: util.write_file(sudo_file, "\n".join(contents), 0o440) - except IOError as e: + except OSError as e: util.logexc(LOG, "Failed to write sudoers file %s", sudo_file) raise e else: if content not in util.load_text_file(sudo_file): try: util.append_file(sudo_file, content) - except IOError as e: + except OSError as e: util.logexc( LOG, "Failed to append to sudoers file %s", sudo_file ) @@ -1316,7 +1316,7 @@ def _get_proc_stat_by_index(pid: int, field: int) -> Optional[int]: ) return None return int(match.group(field)) - except IOError as e: + except OSError as e: LOG.warning("Failed to load /proc/%s/stat. %s", pid, e) except IndexError: LOG.warning( diff --git a/cloudinit/distros/alpine.py b/cloudinit/distros/alpine.py index fa0bbf23cc39..e1b473dd8eaa 100644 --- a/cloudinit/distros/alpine.py +++ b/cloudinit/distros/alpine.py @@ -85,7 +85,7 @@ def _write_hostname(self, hostname, filename): # Try to update the previous one # so lets see if we can read it first. conf = self._read_hostname_conf(filename) - except IOError: + except OSError: create_hostname_file = util.get_cfg_option_bool( self._cfg, "create_hostname_file", True ) @@ -115,7 +115,7 @@ def _read_hostname(self, filename, default=None): try: conf = self._read_hostname_conf(filename) hostname = conf.hostname - except IOError: + except OSError: pass if not hostname: return default diff --git a/cloudinit/distros/arch.py b/cloudinit/distros/arch.py index 521c014d7205..d8f180b70b2f 100644 --- a/cloudinit/distros/arch.py +++ b/cloudinit/distros/arch.py @@ -64,7 +64,7 @@ def _write_hostname(self, hostname, filename): # Try to update the previous one # so lets see if we can read it first. conf = self._read_hostname_conf(filename) - except IOError: + except OSError: create_hostname_file = util.get_cfg_option_bool( self._cfg, "create_hostname_file", True ) @@ -94,7 +94,7 @@ def _read_hostname(self, filename, default=None): try: conf = self._read_hostname_conf(filename) hostname = conf.hostname - except IOError: + except OSError: pass if not hostname: return default diff --git a/cloudinit/distros/debian.py b/cloudinit/distros/debian.py index a21408eea519..6a017a31d1aa 100644 --- a/cloudinit/distros/debian.py +++ b/cloudinit/distros/debian.py @@ -130,7 +130,7 @@ def _write_hostname(self, hostname, filename): # Try to update the previous one # so lets see if we can read it first. conf = self._read_hostname_conf(filename) - except IOError: + except OSError: create_hostname_file = util.get_cfg_option_bool( self._cfg, "create_hostname_file", True ) @@ -160,7 +160,7 @@ def _read_hostname(self, filename, default=None): try: conf = self._read_hostname_conf(filename) hostname = conf.hostname - except IOError: + except OSError: pass if not hostname: return default diff --git a/cloudinit/distros/freebsd.py b/cloudinit/distros/freebsd.py index 2d8fa02fea6d..f807ce9cb76a 100644 --- a/cloudinit/distros/freebsd.py +++ b/cloudinit/distros/freebsd.py @@ -193,7 +193,7 @@ def apply_locale(self, locale, out_fn=None): util.logexc(LOG, "Failed to apply locale %s", locale) try: util.copy(self.login_conf_fn_bak, self.login_conf_fn) - except IOError: + except OSError: util.logexc( LOG, "Failed to restore %s backup", self.login_conf_fn ) diff --git a/cloudinit/distros/gentoo.py b/cloudinit/distros/gentoo.py index 37ac7b68cf76..d93387643312 100644 --- a/cloudinit/distros/gentoo.py +++ b/cloudinit/distros/gentoo.py @@ -63,7 +63,7 @@ def _write_hostname(self, hostname, filename): # Try to update the previous one # so lets see if we can read it first. conf = self._read_hostname_conf(filename) - except IOError: + except OSError: create_hostname_file = util.get_cfg_option_bool( self._cfg, "create_hostname_file", True ) @@ -98,7 +98,7 @@ def _read_hostname(self, filename, default=None): try: conf = self._read_hostname_conf(filename) hostname = conf.hostname - except IOError: + except OSError: pass if not hostname: return default diff --git a/cloudinit/distros/opensuse.py b/cloudinit/distros/opensuse.py index 8cf41b5d6bb2..ff2907e95e92 100644 --- a/cloudinit/distros/opensuse.py +++ b/cloudinit/distros/opensuse.py @@ -171,7 +171,7 @@ def _read_hostname(self, filename, default=None): try: conf = self._read_hostname_conf(filename) hostname = conf.hostname - except IOError: + except OSError: pass if not hostname: return default @@ -244,7 +244,7 @@ def _write_hostname(self, hostname, filename): # Try to update the previous one # so lets see if we can read it first. conf = self._read_hostname_conf(filename) - except IOError: + except OSError: if create_hostname_file: pass else: diff --git a/cloudinit/distros/parsers/hostname.py b/cloudinit/distros/parsers/hostname.py index 7e498a5fab1f..704e179b2f03 100644 --- a/cloudinit/distros/parsers/hostname.py +++ b/cloudinit/distros/parsers/hostname.py @@ -71,5 +71,5 @@ def _parse(self, contents): entries.append(("hostname", [head, tail])) hostnames_found.add(head) if len(hostnames_found) > 1: - raise IOError("Multiple hostnames (%s) found!" % (hostnames_found)) + raise OSError("Multiple hostnames (%s) found!" % (hostnames_found)) return entries diff --git a/cloudinit/distros/parsers/resolv_conf.py b/cloudinit/distros/parsers/resolv_conf.py index 000d0b577ab6..5e769b53a01b 100644 --- a/cloudinit/distros/parsers/resolv_conf.py +++ b/cloudinit/distros/parsers/resolv_conf.py @@ -148,7 +148,7 @@ def _parse(self, contents): try: (cfg_opt, cfg_values) = head.split(None, 1) except (IndexError, ValueError) as e: - raise IOError( + raise OSError( "Incorrectly formatted resolv.conf line %s" % (i + 1) ) from e if cfg_opt not in [ @@ -158,6 +158,6 @@ def _parse(self, contents): "sortlist", "options", ]: - raise IOError("Unexpected resolv.conf option %s" % (cfg_opt)) + raise OSError("Unexpected resolv.conf option %s" % (cfg_opt)) entries.append(("option", [cfg_opt, cfg_values, tail])) return entries diff --git a/cloudinit/distros/rhel_util.py b/cloudinit/distros/rhel_util.py index 426335f9b964..28e657e47403 100644 --- a/cloudinit/distros/rhel_util.py +++ b/cloudinit/distros/rhel_util.py @@ -45,6 +45,6 @@ def read_sysconfig_file(fn): try: contents = util.load_text_file(fn).splitlines() exists = True - except IOError: + except OSError: contents = [] return (exists, SysConf(contents)) diff --git a/cloudinit/helpers.py b/cloudinit/helpers.py index 40d389a097cf..650334dd88de 100644 --- a/cloudinit/helpers.py +++ b/cloudinit/helpers.py @@ -70,7 +70,7 @@ def clear(self, name, freq): sem_file = self._get_path(name, freq) try: util.del_file(sem_file) - except (IOError, OSError): + except OSError: util.logexc(LOG, "Failed deleting semaphore %s", sem_file) return False return True @@ -86,7 +86,7 @@ def _acquire(self, name, freq): contents = "%s: %s\n" % (os.getpid(), time()) try: util.write_file(sem_file, contents) - except (IOError, OSError): + except OSError: util.logexc(LOG, "Failed writing semaphore file %s", sem_file) return None return FileLock(sem_file) diff --git a/cloudinit/log.py b/cloudinit/log.py index 08d0efa30015..624f6c2a9e7e 100644 --- a/cloudinit/log.py +++ b/cloudinit/log.py @@ -40,7 +40,7 @@ def flush_loggers(root): return for h in root.handlers: if isinstance(h, (logging.StreamHandler)): - with suppress(IOError): + with suppress(OSError): h.flush() flush_loggers(root.parent) @@ -159,7 +159,7 @@ def setup_backup_logging(): def handleError(self, record): """A closure that emits logs on stderr when other methods fail""" - with suppress(IOError): + with suppress(OSError): fallback_handler.handle(record) fallback_handler.flush() diff --git a/cloudinit/net/bsd.py b/cloudinit/net/bsd.py index 0b0ff1592d8b..7a7ff9e284fc 100644 --- a/cloudinit/net/bsd.py +++ b/cloudinit/net/bsd.py @@ -171,7 +171,7 @@ def _resolve_conf(self, settings): ) ) resolvconf.parse() - except IOError: + except OSError: util.logexc( LOG, "Failed to parse %s, use new empty file", diff --git a/cloudinit/net/cmdline.py b/cloudinit/net/cmdline.py index 903300fbb168..03b0c04a9028 100644 --- a/cloudinit/net/cmdline.py +++ b/cloudinit/net/cmdline.py @@ -244,7 +244,7 @@ def _decomp_gzip(blob): try: gzfp = gzip.GzipFile(mode="rb", fileobj=iobuf) return gzfp.read() - except IOError: + except OSError: return blob finally: if gzfp: diff --git a/cloudinit/reporting/handlers.py b/cloudinit/reporting/handlers.py index 42b14b1a7a2d..98da99ac3977 100644 --- a/cloudinit/reporting/handlers.py +++ b/cloudinit/reporting/handlers.py @@ -242,7 +242,7 @@ def _truncate_guest_pool_file(cls, kvp_file): if os.path.getmtime(kvp_file) < boot_time: with open(kvp_file, "w"): pass - except (OSError, IOError) as e: + except OSError as e: LOG.warning("failed to truncate kvp pool file, %s", e) finally: cls._already_truncated_pool_file = True @@ -367,7 +367,7 @@ def write_key(self, key: str, value: str) -> None: try: self._append_kvp_item(data) - except (OSError, IOError): + except OSError: LOG.warning("failed posting kvp=%s value=%s", key, value) def _encode_event(self, event): @@ -414,7 +414,7 @@ def _publish_event_routine(self): event = None try: self._append_kvp_item(encoded_data) - except (OSError, IOError) as e: + except OSError as e: LOG.warning("failed posting events to kvp, %s", e) finally: for _ in range(items_from_queue): diff --git a/cloudinit/sources/DataSourceAltCloud.py b/cloudinit/sources/DataSourceAltCloud.py index aeecd15d05f6..c6cf0bfad01e 100644 --- a/cloudinit/sources/DataSourceAltCloud.py +++ b/cloudinit/sources/DataSourceAltCloud.py @@ -59,10 +59,10 @@ def read_user_data_callback(mount_dir): # First try deltacloud_user_data_file. On failure try user_data_file. try: user_data = util.load_text_file(deltacloud_user_data_file).strip() - except IOError: + except OSError: try: user_data = util.load_text_file(user_data_file).strip() - except IOError: + except OSError: util.logexc(LOG, "Failed accessing user data file.") return None @@ -109,7 +109,7 @@ def get_cloud_type(self): cloud_type = ( util.load_text_file(CLOUD_INFO_FILE).strip().upper() ) - except IOError: + except OSError: util.logexc( LOG, "Unable to access cloud info file at %s.", diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py index 19730f3c9b09..8f500afde67a 100644 --- a/cloudinit/sources/DataSourceAzure.py +++ b/cloudinit/sources/DataSourceAzure.py @@ -1921,7 +1921,7 @@ def _check_freebsd_cdrom(cdrom_dev): with open(cdrom_dev) as fp: fp.read(1024) return True - except IOError: + except OSError: LOG.debug("cdrom (%s) is not configured", cdrom_dev) return False diff --git a/cloudinit/sources/DataSourceBigstep.py b/cloudinit/sources/DataSourceBigstep.py index cef1489b78ce..5342bf1167dc 100644 --- a/cloudinit/sources/DataSourceBigstep.py +++ b/cloudinit/sources/DataSourceBigstep.py @@ -42,7 +42,7 @@ def _get_url_from_file(self): ) try: content = util.load_text_file(url_file) - except IOError as e: + except OSError as e: # If the file doesn't exist, then the server probably isn't a # Bigstep instance; otherwise, another problem exists which needs # investigation diff --git a/cloudinit/sources/DataSourceConfigDrive.py b/cloudinit/sources/DataSourceConfigDrive.py index 9ddf275d8d9e..33478915db44 100644 --- a/cloudinit/sources/DataSourceConfigDrive.py +++ b/cloudinit/sources/DataSourceConfigDrive.py @@ -216,7 +216,7 @@ def get_previous_iid(paths): fname = os.path.join(paths.get_cpath("data"), "instance-id") try: return util.load_text_file(fname).rstrip("\n") - except IOError: + except OSError: return None @@ -242,7 +242,7 @@ def write_injected_files(files): filename = os.sep + filename try: util.write_file(filename, content, mode=0o660) - except IOError: + except OSError: util.logexc(LOG, "Failed writing file: %s", filename) diff --git a/cloudinit/sources/DataSourceIBMCloud.py b/cloudinit/sources/DataSourceIBMCloud.py index 16d8ce12e60b..07ca61eff353 100644 --- a/cloudinit/sources/DataSourceIBMCloud.py +++ b/cloudinit/sources/DataSourceIBMCloud.py @@ -361,7 +361,7 @@ def load_json_bytes(blob): raw = None try: raw = util.load_binary_file(fpath) - except IOError as e: + except OSError as e: LOG.debug("Failed reading path '%s': %s", fpath, e) if raw is None or transl is None: diff --git a/cloudinit/sources/DataSourceOpenNebula.py b/cloudinit/sources/DataSourceOpenNebula.py index 5ad3b6bc6c11..33ce0ff3b46d 100644 --- a/cloudinit/sources/DataSourceOpenNebula.py +++ b/cloudinit/sources/DataSourceOpenNebula.py @@ -430,7 +430,7 @@ def read_context_disk_dir(source_dir, distro, asuser=None): raise BrokenContextDiskDir( "Error processing context.sh: %s" % (e) ) from e - except IOError as e: + except OSError as e: raise NonContextDiskDir( "Error reading context.sh: %s" % (e) ) from e diff --git a/cloudinit/sources/DataSourceOpenStack.py b/cloudinit/sources/DataSourceOpenStack.py index 22ecee7af610..1e9e024d4f15 100644 --- a/cloudinit/sources/DataSourceOpenStack.py +++ b/cloudinit/sources/DataSourceOpenStack.py @@ -211,9 +211,9 @@ def _crawl_metadata(self): raise sources.InvalidMetaDataException( "No active metadata service found" ) - except IOError as e: + except OSError as e: raise sources.InvalidMetaDataException( - "IOError contacting metadata service: {error}".format( + "OSError contacting metadata service: {error}".format( error=str(e) ) ) @@ -234,7 +234,7 @@ def _crawl_metadata(self): ) except openstack.NonReadable as e: raise sources.InvalidMetaDataException(str(e)) - except (openstack.BrokenMetadata, IOError) as e: + except (openstack.BrokenMetadata, OSError) as e: msg = "Broken metadata address {addr}".format( addr=self.metadata_address ) diff --git a/cloudinit/sources/DataSourceSmartOS.py b/cloudinit/sources/DataSourceSmartOS.py index 801b56b135eb..7c642180cc7e 100644 --- a/cloudinit/sources/DataSourceSmartOS.py +++ b/cloudinit/sources/DataSourceSmartOS.py @@ -806,7 +806,7 @@ def write_boot_content( if content and os.path.exists(content_f): util.ensure_dir(os.path.dirname(link)) os.symlink(content_f, link) - except IOError as e: + except OSError as e: util.logexc(LOG, "failed establishing content link: %s", e) diff --git a/cloudinit/sources/DataSourceWSL.py b/cloudinit/sources/DataSourceWSL.py index 3d9cf58ebb4a..dd0b57e2adbe 100644 --- a/cloudinit/sources/DataSourceWSL.py +++ b/cloudinit/sources/DataSourceWSL.py @@ -85,7 +85,7 @@ def cmd_executable() -> PurePath: mounts = mounted_win_drives() if not mounts: - raise IOError("Windows drives are not mounted.") + raise OSError("Windows drives are not mounted.") # cmd.exe path is being stable for decades. candidate = "%s/Windows/System32/cmd.exe" @@ -97,7 +97,7 @@ def cmd_executable() -> PurePath: LOG.debug("Found cmd.exe at <%s>", cmd) return PurePath(cmd) - raise IOError( + raise OSError( "Couldn't find cmd.exe in any mount point: %s" % ", ".join(mounts) ) @@ -202,7 +202,7 @@ def find_user_data_file(self, seed_dir: PurePath) -> PurePath: ef.name.casefold(): ef.path for ef in os.scandir(seed_dir) } if not existing_files: - raise IOError("%s directory is empty" % seed_dir) + raise OSError("%s directory is empty" % seed_dir) folded_names = [ f.casefold() @@ -212,7 +212,7 @@ def find_user_data_file(self, seed_dir: PurePath) -> PurePath: if filename in existing_files.keys(): return PurePath(existing_files[filename]) - raise IOError( + raise OSError( "%s doesn't contain any of the expected user-data files" % seed_dir ) @@ -229,7 +229,7 @@ def check_instance_id(self, sys_cfg) -> bool: ) return current == metadata.get("instance-id") - except (IOError, ValueError) as err: + except (OSError, ValueError) as err: LOG.warning( "Unable to check_instance_id from metadata file: %s", str(err), @@ -250,7 +250,7 @@ def _get_data(self) -> bool: ) return True - except (ValueError, IOError) as err: + except (ValueError, OSError) as err: LOG.error("Unable to setup WSL datasource: %s", str(err)) return False diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py index aeb7a8018205..01b88dde47c6 100644 --- a/cloudinit/sources/__init__.py +++ b/cloudinit/sources/__init__.py @@ -1158,7 +1158,7 @@ def convert_vendordata(data, recurse=True): raise ValueError("Unknown data type for vendordata: %s" % type(data)) -class BrokenMetadata(IOError): +class BrokenMetadata(OSError): pass diff --git a/cloudinit/sources/helpers/openstack.py b/cloudinit/sources/helpers/openstack.py index 4617f8142c48..d633a7be0584 100644 --- a/cloudinit/sources/helpers/openstack.py +++ b/cloudinit/sources/helpers/openstack.py @@ -79,7 +79,7 @@ ) -class NonReadable(IOError): +class NonReadable(OSError): pass @@ -341,7 +341,7 @@ def datafiles(version): try: content = self._read_content_path(net_item, decode=True) results["network_config"] = content - except IOError as e: + except OSError as e: raise BrokenMetadata( "Failed to read network configuration: %s" % (e) ) from e @@ -430,7 +430,7 @@ def read_v1(self): path = found[name] try: contents = self._path_read(path) - except IOError as e: + except OSError as e: raise BrokenMetadata("Failed to read: %s" % path) from e try: # Disable not-callable pylint check; pylint isn't able to diff --git a/cloudinit/ssh_util.py b/cloudinit/ssh_util.py index cad85d596b80..18c96740d111 100644 --- a/cloudinit/ssh_util.py +++ b/cloudinit/ssh_util.py @@ -193,7 +193,7 @@ def parse_authorized_keys(fnames): lines = util.load_text_file(fname).splitlines() for line in lines: contents.append(parser.parse(line)) - except (IOError, OSError): + except OSError: util.logexc(LOG, "Error reading lines from %s", fname) return contents @@ -396,7 +396,7 @@ def check_create_path(username, filename, strictmodes): ) if not permissions: return False - except (IOError, OSError) as e: + except OSError as e: util.logexc(LOG, str(e)) return False @@ -419,7 +419,7 @@ def extract_authorized_keys(username, sshd_cfg_file=DEF_SSHD_CFG): key_paths, pw_ent.pw_dir, username ) - except (IOError, OSError): + except OSError: # Give up and use a default key filename auth_key_fns[0] = default_authorizedkeys_file util.logexc( diff --git a/cloudinit/stages.py b/cloudinit/stages.py index c32ce09bbcdf..855884e1a2d2 100644 --- a/cloudinit/stages.py +++ b/cloudinit/stages.py @@ -829,7 +829,7 @@ def consume_data(self, frequency=PER_INSTANCE): instance_json = util.load_json( util.load_text_file(json_sensitive_file) ) - except (OSError, IOError) as e: + except OSError as e: LOG.warning( "Skipping write of system_info/features to %s." " Unable to read file: %s", diff --git a/cloudinit/subp.py b/cloudinit/subp.py index 29a3d1a32e18..c80ba6932897 100644 --- a/cloudinit/subp.py +++ b/cloudinit/subp.py @@ -66,7 +66,7 @@ def prepend_base_command(base_command, commands): return fixed_commands -class ProcessExecutionError(IOError): +class ProcessExecutionError(OSError): MESSAGE_TMPL = ( "%(description)s\n" "Command: %(cmd)s\n" @@ -122,7 +122,7 @@ def __init__( "stderr": self._ensure_string(self.stderr), "reason": self._ensure_string(self.reason), } - IOError.__init__(self, message) + OSError.__init__(self, message) def _ensure_string(self, text): """ diff --git a/cloudinit/url_helper.py b/cloudinit/url_helper.py index f879e80114ca..242105fc4e21 100644 --- a/cloudinit/url_helper.py +++ b/cloudinit/url_helper.py @@ -212,7 +212,7 @@ def _read_file(path: str, **kwargs) -> "FileResponse": return FileResponse(contents, path) except FileNotFoundError as e: raise UrlError(cause=e, code=NOT_FOUND, headers=None, url=path) from e - except IOError as e: + except OSError as e: raise UrlError(cause=e, code=e.errno, headers=None, url=path) from e @@ -321,9 +321,9 @@ def iter_content( yield from self._response.iter_content(chunk_size, decode_unicode) -class UrlError(IOError): +class UrlError(OSError): def __init__(self, cause, code=None, headers=None, url=None): - IOError.__init__(self, str(cause)) + OSError.__init__(self, str(cause)) self.cause = cause self.code = code self.headers = headers diff --git a/cloudinit/user_data.py b/cloudinit/user_data.py index e6b118e82fe6..c2b535403428 100644 --- a/cloudinit/user_data.py +++ b/cloudinit/user_data.py @@ -265,7 +265,7 @@ def _do_include(self, content, append_msg): if include_url not in message: message += " for url: {0}".format(include_url) _handle_error(message, urle) - except IOError as ioe: + except OSError as ioe: error_message = "Fetching from {} resulted in {}".format( include_url, ioe ) diff --git a/cloudinit/util.py b/cloudinit/util.py index ce6f97e2859a..4f05e75e526c 100644 --- a/cloudinit/util.py +++ b/cloudinit/util.py @@ -1302,7 +1302,7 @@ def get_fqdn_from_hosts(hostname, filename="/etc/hosts"): if hostname in toks[2:]: fqdn = toks[1] break - except IOError: + except OSError: pass return fqdn @@ -1668,7 +1668,7 @@ def fips_enabled() -> bool: try: contents = load_text_file(fips_proc).strip() return contents == "1" - except (IOError, OSError): + except OSError: # for BSD systems and Linux systems where the proc entry is not # available, we assume FIPS is disabled to retain the old behavior # for now. @@ -1972,7 +1972,7 @@ def mounts(): "opts": opts, } LOG.debug("Fetched %s mounts from %s", mounted, method) - except (IOError, OSError): + except OSError: logexc(LOG, "Failed fetching mount points") return mounted @@ -2042,7 +2042,7 @@ def mount_cb( umount = tmpd # This forces it to be unmounted (when set) mountpoint = tmpd break - except (IOError, OSError) as exc: + except OSError as exc: if log_error: LOG.debug( "Failed to mount device: '%s' with type: '%s' " @@ -2451,7 +2451,7 @@ def is_container(): return True if "LIBVIRT_LXC_UUID" in pid1env: return True - except (IOError, OSError): + except OSError: pass # Detect OpenVZ containers @@ -2466,7 +2466,7 @@ def is_container(): (_key, val) = line.strip().split(":", 1) if val != "0": return True - except (IOError, OSError): + except OSError: pass return False @@ -2489,7 +2489,7 @@ def get_proc_env(pid, encoding="utf-8", errors="replace"): try: contents = load_binary_file(fn) - except (IOError, OSError): + except OSError: return {} env = {} diff --git a/tests/integration_tests/instances.py b/tests/integration_tests/instances.py index c31a7c63ffa1..e2db227a637f 100644 --- a/tests/integration_tests/instances.py +++ b/tests/integration_tests/instances.py @@ -111,7 +111,7 @@ def read_from_file(self, remote_path) -> str: if result.failed: # TODO: Raise here whatever pycloudlib raises when it has # a consistent error response - raise IOError( + raise OSError( "Failed reading remote file via cat: {}\n" "Return code: {}\n" "Stderr: {}\n" diff --git a/tests/unittests/cmd/test_query.py b/tests/unittests/cmd/test_query.py index 39f5c565abfa..a0836e977bbc 100644 --- a/tests/unittests/cmd/test_query.py +++ b/tests/unittests/cmd/test_query.py @@ -177,7 +177,7 @@ def test_handle_args_error_when_no_read_permission_instance_data( [ (OSError(errno.EACCES, "Not allowed"),), (OSError(errno.ENOENT, "Not allowed"),), - (IOError,), + (OSError,), ], ) def test_handle_args_error_when_no_read_permission_init_cfg( diff --git a/tests/unittests/config/test_cc_seed_random.py b/tests/unittests/config/test_cc_seed_random.py index 365d1c8530cd..346833d47d64 100644 --- a/tests/unittests/config/test_cc_seed_random.py +++ b/tests/unittests/config/test_cc_seed_random.py @@ -90,7 +90,7 @@ def test_append_random_unknown_encoding(self): } } pytest.raises( - IOError, + OSError, cc_seed_random.handle, "test", cfg, diff --git a/tests/unittests/config/test_cc_yum_add_repo.py b/tests/unittests/config/test_cc_yum_add_repo.py index 1707860a19f9..55c1074c4164 100644 --- a/tests/unittests/config/test_cc_yum_add_repo.py +++ b/tests/unittests/config/test_cc_yum_add_repo.py @@ -43,7 +43,7 @@ def test_bad_config(self): self.patchUtils(self.tmp) cc_yum_add_repo.handle("yum_add_repo", cfg, None, []) self.assertRaises( - IOError, util.load_text_file, "/etc/yum.repos.d/epel_testing.repo" + OSError, util.load_text_file, "/etc/yum.repos.d/epel_testing.repo" ) def test_write_config(self): diff --git a/tests/unittests/config/test_cc_zypper_add_repo.py b/tests/unittests/config/test_cc_zypper_add_repo.py index 772d132ffdfd..c4c341ea68a5 100644 --- a/tests/unittests/config/test_cc_zypper_add_repo.py +++ b/tests/unittests/config/test_cc_zypper_add_repo.py @@ -29,7 +29,7 @@ def test_bad_repo_config(self): self.patchUtils(self.tmp) cc_zypper_add_repo._write_repos(cfg["repos"], "/etc/zypp/repos.d") self.assertRaises( - IOError, util.load_text_file, "/etc/zypp/repos.d/foo.repo" + OSError, util.load_text_file, "/etc/zypp/repos.d/foo.repo" ) def test_write_repos(self): diff --git a/tests/unittests/config/test_schema.py b/tests/unittests/config/test_schema.py index f9d533e12e8d..53574fcaec6d 100644 --- a/tests/unittests/config/test_schema.py +++ b/tests/unittests/config/test_schema.py @@ -2589,7 +2589,7 @@ class TestHandleSchemaArgs: "failure, expected_logs", ( ( - IOError("No permissions on /var/lib/cloud/instance"), + OSError("No permissions on /var/lib/cloud/instance"), ["Using default instance-data/user-data paths for non-root"], ), ( @@ -2609,7 +2609,7 @@ def test_handle_schema_unable_to_read_cfg_paths( caplog, tmpdir, ): - if isinstance(failure, IOError): + if isinstance(failure, OSError): failure.errno = EACCES read_cfg_paths.side_effect = [failure, paths] user_data_fn = tmpdir.join("user-data") diff --git a/tests/unittests/net/test_init.py b/tests/unittests/net/test_init.py index ffccd2c5577a..9b35a1037408 100644 --- a/tests/unittests/net/test_init.py +++ b/tests/unittests/net/test_init.py @@ -61,13 +61,12 @@ def test_read_sys_net_strips_contents_of_sys_path(self): assert content.strip() == net.read_sys_net("dev", "attr") def test_read_sys_net_reraises_oserror(self): - """read_sys_net raises OSError/IOError when file doesn't exist.""" - # Non-specific Exception because versions of python OSError vs IOError. + """read_sys_net raises OSError when file doesn't exist.""" with pytest.raises(Exception, match="No such file or directory"): net.read_sys_net("dev", "attr") def test_read_sys_net_safe_handles_error(self): - """read_sys_net_safe handles OSError/IOError""" + """read_sys_net_safe handles OSError""" assert not net.read_sys_net_safe("dev", "attr") def test_read_sys_net_safe_returns_false_on_noent_failure(self): diff --git a/tests/unittests/sources/test_altcloud.py b/tests/unittests/sources/test_altcloud.py index dba0f6a4d710..0fb58d54fc54 100644 --- a/tests/unittests/sources/test_altcloud.py +++ b/tests/unittests/sources/test_altcloud.py @@ -98,7 +98,7 @@ def test_cloud_info_file_ioerror(self): """Return UNKNOWN when /etc/sysconfig/cloud-info exists but errors.""" self.assertEqual("/etc/sysconfig/cloud-info", dsac.CLOUD_INFO_FILE) dsrc = dsac.DataSourceAltCloud({}, None, self.paths) - # Attempting to read the directory generates IOError + # Attempting to read the directory generates OSError with mock.patch.object(dsac, "CLOUD_INFO_FILE", self.tmp): self.assertEqual("UNKNOWN", dsrc.get_cloud_type()) self.assertIn( @@ -110,7 +110,7 @@ def test_cloud_info_file(self): dsrc = dsac.DataSourceAltCloud({}, None, self.paths) cloud_info = self.tmp_path("cloud-info", dir=self.tmp) util.write_file(cloud_info, " OverRiDdeN CloudType ") - # Attempting to read the directory generates IOError + # Attempting to read the directory generates OSError with mock.patch.object(dsac, "CLOUD_INFO_FILE", cloud_info): self.assertEqual("OVERRIDDEN CLOUDTYPE", dsrc.get_cloud_type()) diff --git a/tests/unittests/sources/test_wsl.py b/tests/unittests/sources/test_wsl.py index 9f5c40fcd014..2afd05557aa9 100644 --- a/tests/unittests/sources/test_wsl.py +++ b/tests/unittests/sources/test_wsl.py @@ -106,7 +106,7 @@ def test_cmd_not_executable(self, m_mounts, m_os_access): assert None is not cmd.relative_to(GOOD_MOUNTS["C:\\"]["mountpoint"]) m_os_access.return_value = False - with pytest.raises(IOError): + with pytest.raises(OSError): wsl.cmd_executable() @mock.patch("os.access") @@ -120,7 +120,7 @@ def test_cmd_exe_no_win_mounts(self, m_mounts, m_os_access): m_mounts.return_value = deepcopy(GOOD_MOUNTS) m_mounts.return_value.pop("C:\\") m_mounts.return_value.pop("D:\\") - with pytest.raises(IOError): + with pytest.raises(OSError): wsl.cmd_executable() @pytest.mark.parametrize( diff --git a/tests/unittests/test_merging.py b/tests/unittests/test_merging.py index 81c878d2ee25..28a7e66a2478 100644 --- a/tests/unittests/test_merging.py +++ b/tests/unittests/test_merging.py @@ -110,14 +110,14 @@ def _load_merge_files(self): base_fn = os.path.basename(fn) file_id = re.match(r"source(\d+)\-(\d+)[.]yaml", base_fn) if not file_id: - raise IOError( + raise OSError( "File %s does not have a numeric identifier" % (fn) ) file_id = int(file_id.group(1)) source_ids[file_id].append(fn) expected_fn = os.path.join(merge_root, EXPECTED_PAT % (file_id)) if not os.path.isfile(expected_fn): - raise IOError("No expected file found at %s" % (expected_fn)) + raise OSError("No expected file found at %s" % (expected_fn)) expected_files[file_id] = expected_fn for i in sorted(source_ids.keys()): source_file_contents = [] diff --git a/tests/unittests/test_ssh_util.py b/tests/unittests/test_ssh_util.py index cd78f75b7393..2fdcd7370fc5 100644 --- a/tests/unittests/test_ssh_util.py +++ b/tests/unittests/test_ssh_util.py @@ -378,7 +378,7 @@ class TestParseSSHConfig: "is_file, file_content", [ pytest.param(True, ("",), id="empty-file"), - pytest.param(False, IOError, id="not-a-file"), + pytest.param(False, OSError, id="not-a-file"), ], ) def test_dummy_file(self, m_is_file, m_load_file, is_file, file_content): diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py index 2aa387b76221..0fa1507dacd0 100644 --- a/tests/unittests/test_util.py +++ b/tests/unittests/test_util.py @@ -2052,7 +2052,7 @@ def test_fips_enabled_based_on_proc_crypto( def fake_load_file(path): assert path == "/proc/sys/crypto/fips_enabled" if fips_enabled_content is None: - raise IOError("No file exists Bob") + raise OSError("No file exists Bob") return fips_enabled_content load_file.side_effect = fake_load_file @@ -2604,7 +2604,7 @@ def test_pexec_error_indent_text(self): ) def test_pexec_error_type(self): - self.assertIsInstance(subp.ProcessExecutionError(), IOError) + self.assertIsInstance(subp.ProcessExecutionError(), OSError) def test_pexec_error_empty_msgs(self): error = subp.ProcessExecutionError()