diff options
author | James Falcon <james.falcon@canonical.com> | 2021-12-15 20:16:38 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-15 19:16:38 -0700 |
commit | bae9b11da9ed7dd0b16fe5adeaf4774b7cc628cf (patch) | |
tree | 1fbb3269fc87e39832e3286ef42eefd2b23fcd44 /cloudinit/distros | |
parent | 2bcf4fa972fde686c2e3141c58e640640b44dd00 (diff) | |
download | vyos-cloud-init-bae9b11da9ed7dd0b16fe5adeaf4774b7cc628cf.tar.gz vyos-cloud-init-bae9b11da9ed7dd0b16fe5adeaf4774b7cc628cf.zip |
Adopt Black and isort (SC-700) (#1157)
Applied Black and isort, fixed any linting issues, updated tox.ini
and CI.
Diffstat (limited to 'cloudinit/distros')
36 files changed, 1041 insertions, 848 deletions
diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py index 742804ea..de000b52 100755 --- a/cloudinit/distros/__init__.py +++ b/cloudinit/distros/__init__.py @@ -20,49 +20,49 @@ from typing import Any, Mapping # noqa: F401 from cloudinit import importer from cloudinit import log as logging -from cloudinit import net -from cloudinit.net import activators -from cloudinit.net import eni -from cloudinit.net import network_state -from cloudinit.net import renderers +from cloudinit import net, persistence, ssh_util, subp, type_utils, util +from cloudinit.distros.parsers import hosts +from cloudinit.features import ALLOW_EC2_MIRRORS_ON_NON_AWS_INSTANCE_TYPES +from cloudinit.net import activators, eni, network_state, renderers from cloudinit.net.network_state import parse_net_config_data -from cloudinit import persistence -from cloudinit import ssh_util -from cloudinit import type_utils -from cloudinit import subp -from cloudinit import util - -from cloudinit.features import \ - ALLOW_EC2_MIRRORS_ON_NON_AWS_INSTANCE_TYPES -from cloudinit.distros.parsers import hosts from .networking import LinuxNetworking - # Used when a cloud-config module can be run on all cloud-init distibutions. # The value 'all' is surfaced in module documentation for distro support. -ALL_DISTROS = 'all' +ALL_DISTROS = "all" OSFAMILIES = { - 'alpine': ['alpine'], - 'arch': ['arch'], - 'debian': ['debian', 'ubuntu'], - 'freebsd': ['freebsd'], - 'gentoo': ['gentoo'], - 'redhat': ['almalinux', 'amazon', 'centos', 'cloudlinux', 'eurolinux', - 'fedora', 'miraclelinux', 'openEuler', 'photon', 'rhel', - 'rocky', 'virtuozzo'], - 'suse': ['opensuse', 'sles'], + "alpine": ["alpine"], + "arch": ["arch"], + "debian": ["debian", "ubuntu"], + "freebsd": ["freebsd"], + "gentoo": ["gentoo"], + "redhat": [ + "almalinux", + "amazon", + "centos", + "cloudlinux", + "eurolinux", + "fedora", + "miraclelinux", + "openEuler", + "photon", + "rhel", + "rocky", + "virtuozzo", + ], + "suse": ["opensuse", "sles"], } LOG = logging.getLogger(__name__) # This is a best guess regex, based on current EC2 AZs on 2017-12-11. # It could break when Amazon adds new regions and new AZs. -_EC2_AZ_RE = re.compile('^[a-z][a-z]-(?:[a-z]+-)+[0-9][a-z]$') +_EC2_AZ_RE = re.compile("^[a-z][a-z]-(?:[a-z]+-)+[0-9][a-z]$") # Default NTP Client Configurations -PREFERRED_NTP_CLIENTS = ['chrony', 'systemd-timesyncd', 'ntp', 'ntpdate'] +PREFERRED_NTP_CLIENTS = ["chrony", "systemd-timesyncd", "ntp", "ntpdate"] # Letters/Digits/Hyphen characters, for use in domain name validation LDH_ASCII_CHARS = string.ascii_letters + string.digits + "-" @@ -75,13 +75,13 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): ci_sudoers_fn = "/etc/sudoers.d/90-cloud-init-users" hostname_conf_fn = "/etc/hostname" tz_zone_dir = "/usr/share/zoneinfo" - init_cmd = ['service'] # systemctl, service etc + init_cmd = ["service"] # systemctl, service etc renderer_configs = {} # type: Mapping[str, Mapping[str, Any]] _preferred_ntp_clients = None networking_cls = LinuxNetworking # This is used by self.shutdown_command(), and can be overridden in # subclasses - shutdown_options_map = {'halt': '-H', 'poweroff': '-P', 'reboot': '-r'} + shutdown_options_map = {"halt": "-H", "poweroff": "-P", "reboot": "-r"} _ci_pkl_version = 1 prefer_fqdn = False @@ -113,23 +113,27 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): """Deprecated. Remove if/when arch and gentoo support renderers.""" raise NotImplementedError( "Legacy function '_write_network' was called in distro '%s'.\n" - "_write_network_config needs implementation.\n" % self.name) + "_write_network_config needs implementation.\n" % self.name + ) def _write_network_state(self, network_state): priority = util.get_cfg_by_path( - self._cfg, ('network', 'renderers'), None) + self._cfg, ("network", "renderers"), None + ) name, render_cls = renderers.select(priority=priority) - LOG.debug("Selected renderer '%s' from priority list: %s", - name, priority) + LOG.debug( + "Selected renderer '%s' from priority list: %s", name, priority + ) renderer = render_cls(config=self.renderer_configs.get(name)) renderer.render_network_state(network_state) 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(("Invalid timezone %s," - " no file found at %s") % (tz, tz_file)) + raise IOError( + "Invalid timezone %s, no file found at %s" % (tz, tz_file) + ) return tz_file def get_option(self, opt_name, default=None): @@ -171,8 +175,9 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): # This resolves the package_mirrors config option # down to a single dict of {mirror_name: mirror_url} arch_info = self._get_arch_package_mirror_info(arch) - return _get_package_mirror_info(data_source=data_source, - mirror_info=arch_info) + return _get_package_mirror_info( + data_source=data_source, mirror_info=arch_info + ) def apply_network(self, settings, bring_up=True): """Deprecated. Remove if/when arch and gentoo support renderers.""" @@ -192,16 +197,21 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): def _apply_network_from_network_config(self, netconfig, bring_up=True): """Deprecated. Remove if/when arch and gentoo support renderers.""" distro = self.__class__ - LOG.warning("apply_network_config is not currently implemented " - "for distribution '%s'. Attempting to use apply_network", - distro) - header = '\n'.join([ - "# Converted from network_config for distro %s" % distro, - "# Implementation of _write_network_config is needed." - ]) + LOG.warning( + "apply_network_config is not currently implemented " + "for distribution '%s'. Attempting to use apply_network", + distro, + ) + header = "\n".join( + [ + "# Converted from network_config for distro %s" % distro, + "# Implementation of _write_network_config is needed.", + ] + ) ns = network_state.parse_net_config_data(netconfig) contents = eni.network_state_to_eni( - ns, header=header, render_hwaddress=True) + ns, header=header, render_hwaddress=True + ) return self.apply_network(contents, bring_up=bring_up) def generate_fallback_config(self): @@ -224,16 +234,19 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): except NotImplementedError: # backwards compat until all distros have apply_network_config return self._apply_network_from_network_config( - netconfig, bring_up=bring_up) + netconfig, bring_up=bring_up + ) # Now try to bring them up if bring_up: - LOG.debug('Bringing up newly configured network interfaces') + LOG.debug("Bringing up newly configured network interfaces") try: network_activator = activators.select_activator() except activators.NoActivatorException: - LOG.warning("No network activator found, not bringing up " - "network interfaces") + LOG.warning( + "No network activator found, not bringing up " + "network interfaces" + ) return True network_activator.bring_up_all_interfaces(network_state) else: @@ -274,19 +287,27 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): # temporarily (until reboot so it should # not be depended on). Use the write # hostname functions for 'permanent' adjustments. - LOG.debug("Non-persistently setting the system hostname to %s", - hostname) + LOG.debug( + "Non-persistently setting the system hostname to %s", hostname + ) try: - subp.subp(['hostname', hostname]) + subp.subp(["hostname", hostname]) except subp.ProcessExecutionError: - util.logexc(LOG, "Failed to non-persistently adjust the system " - "hostname to %s", hostname) + util.logexc( + LOG, + "Failed to non-persistently adjust the system hostname to %s", + hostname, + ) def _select_hostname(self, hostname, fqdn): # Prefer the short hostname over the long # fully qualified domain name - if util.get_cfg_option_bool(self._cfg, "prefer_fqdn_over_hostname", - self.prefer_fqdn) and fqdn: + if ( + util.get_cfg_option_bool( + self._cfg, "prefer_fqdn_over_hostname", self.prefer_fqdn + ) + and fqdn + ): return fqdn if not hostname: return fqdn @@ -329,32 +350,39 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): # If the system hostname is different than the previous # one or the desired one lets update it as well - if ((not sys_hostname) or (sys_hostname == prev_hostname and - sys_hostname != hostname)): + if (not sys_hostname) or ( + sys_hostname == prev_hostname and sys_hostname != hostname + ): update_files.append(sys_fn) # If something else has changed the hostname after we set it # initially, we should not overwrite those changes (we should # only be setting the hostname once per instance) - if (sys_hostname and prev_hostname and - sys_hostname != prev_hostname): - LOG.info("%s differs from %s, assuming user maintained hostname.", - prev_hostname_fn, sys_fn) + if sys_hostname and prev_hostname and sys_hostname != prev_hostname: + LOG.info( + "%s differs from %s, assuming user maintained hostname.", + prev_hostname_fn, + sys_fn, + ) return # Remove duplicates (incase the previous config filename) # is the same as the system config filename, don't bother # doing it twice update_files = set([f for f in update_files if f]) - LOG.debug("Attempting to update hostname to %s in %s files", - hostname, len(update_files)) + LOG.debug( + "Attempting to update hostname to %s in %s files", + hostname, + len(update_files), + ) for fn in update_files: try: self._write_hostname(hostname, fn) except IOError: - util.logexc(LOG, "Failed to write hostname %s to %s", hostname, - fn) + util.logexc( + LOG, "Failed to write hostname %s to %s", hostname, fn + ) # If the system hostname file name was provided set the # non-fqdn as the transient hostname. @@ -362,11 +390,11 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): self._apply_hostname(applying_hostname) def update_etc_hosts(self, hostname, fqdn): - header = '' + header = "" if os.path.exists(self.hosts_fn): eh = hosts.HostsConf(util.load_file(self.hosts_fn)) else: - eh = hosts.HostsConf('') + eh = hosts.HostsConf("") header = util.make_header(base="added") local_ip = self._get_localhost_ip() prev_info = eh.get_entry(local_ip) @@ -427,7 +455,7 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): return False def get_default_user(self): - return self.get_option('default_user') + return self.get_option("default_user") def add_user(self, name, **kwargs): """ @@ -443,43 +471,43 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): LOG.info("User %s already exists, skipping.", name) return - if 'create_groups' in kwargs: - create_groups = kwargs.pop('create_groups') + if "create_groups" in kwargs: + create_groups = kwargs.pop("create_groups") else: create_groups = True - useradd_cmd = ['useradd', name] - log_useradd_cmd = ['useradd', name] + useradd_cmd = ["useradd", name] + log_useradd_cmd = ["useradd", name] if util.system_is_snappy(): - useradd_cmd.append('--extrausers') - log_useradd_cmd.append('--extrausers') + useradd_cmd.append("--extrausers") + log_useradd_cmd.append("--extrausers") # Since we are creating users, we want to carefully validate the # inputs. If something goes wrong, we can end up with a system # that nobody can login to. useradd_opts = { - "gecos": '--comment', - "homedir": '--home', - "primary_group": '--gid', - "uid": '--uid', - "groups": '--groups', - "passwd": '--password', - "shell": '--shell', - "expiredate": '--expiredate', - "inactive": '--inactive', - "selinux_user": '--selinux-user', + "gecos": "--comment", + "homedir": "--home", + "primary_group": "--gid", + "uid": "--uid", + "groups": "--groups", + "passwd": "--password", + "shell": "--shell", + "expiredate": "--expiredate", + "inactive": "--inactive", + "selinux_user": "--selinux-user", } useradd_flags = { - "no_user_group": '--no-user-group', - "system": '--system', - "no_log_init": '--no-log-init', + "no_user_group": "--no-user-group", + "system": "--system", + "no_log_init": "--no-log-init", } - redact_opts = ['passwd'] + redact_opts = ["passwd"] # support kwargs having groups=[list] or groups="g1,g2" - groups = kwargs.get('groups') + groups = kwargs.get("groups") if groups: if isinstance(groups, str): groups = groups.split(",") @@ -490,9 +518,9 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): # kwargs.items loop below wants a comma delimeted string # that can go right through to the command. - kwargs['groups'] = ",".join(groups) + kwargs["groups"] = ",".join(groups) - primary_group = kwargs.get('primary_group') + primary_group = kwargs.get("primary_group") if primary_group: groups.append(primary_group) @@ -510,7 +538,7 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): # Redact certain fields from the logs if key in redact_opts: - log_useradd_cmd.extend([useradd_opts[key], 'REDACTED']) + log_useradd_cmd.extend([useradd_opts[key], "REDACTED"]) else: log_useradd_cmd.extend([useradd_opts[key], val]) @@ -520,12 +548,12 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): # Don't create the home directory if directed so or if the user is a # system user - if kwargs.get('no_create_home') or kwargs.get('system'): - useradd_cmd.append('-M') - log_useradd_cmd.append('-M') + if kwargs.get("no_create_home") or kwargs.get("system"): + useradd_cmd.append("-M") + log_useradd_cmd.append("-M") else: - useradd_cmd.append('-m') - log_useradd_cmd.append('-m') + useradd_cmd.append("-m") + log_useradd_cmd.append("-m") # Run the command LOG.debug("Adding user %s", name) @@ -540,8 +568,8 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): Add a snappy user to the system using snappy tools """ - snapuser = kwargs.get('snapuser') - known = kwargs.get('known', False) + snapuser = kwargs.get("snapuser") + known = kwargs.get("known", False) create_user_cmd = ["snap", "create-user", "--sudoer", "--json"] if known: create_user_cmd.append("--known") @@ -550,11 +578,12 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): # Run the command LOG.debug("Adding snap user %s", name) try: - (out, err) = subp.subp(create_user_cmd, logstring=create_user_cmd, - capture=True) + (out, err) = subp.subp( + create_user_cmd, logstring=create_user_cmd, capture=True + ) LOG.debug("snap create-user returned: %s:%s", out, err) jobj = util.load_json(out) - username = jobj.get('username', None) + username = jobj.get("username", None) except Exception as e: util.logexc(LOG, "Failed to create snap user %s", name) raise e @@ -582,60 +611,66 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): """ # Add a snap user, if requested - if 'snapuser' in kwargs: + if "snapuser" in kwargs: return self.add_snap_user(name, **kwargs) # Add the user self.add_user(name, **kwargs) # Set password if plain-text password provided and non-empty - if 'plain_text_passwd' in kwargs and kwargs['plain_text_passwd']: - self.set_passwd(name, kwargs['plain_text_passwd']) + if "plain_text_passwd" in kwargs and kwargs["plain_text_passwd"]: + self.set_passwd(name, kwargs["plain_text_passwd"]) # Set password if hashed password is provided and non-empty - if 'hashed_passwd' in kwargs and kwargs['hashed_passwd']: - self.set_passwd(name, kwargs['hashed_passwd'], hashed=True) + if "hashed_passwd" in kwargs and kwargs["hashed_passwd"]: + self.set_passwd(name, kwargs["hashed_passwd"], hashed=True) # Default locking down the account. 'lock_passwd' defaults to True. # lock account unless lock_password is False. - if kwargs.get('lock_passwd', True): + if kwargs.get("lock_passwd", True): self.lock_passwd(name) # Configure sudo access - if 'sudo' in kwargs and kwargs['sudo'] is not False: - self.write_sudo_rules(name, kwargs['sudo']) + if "sudo" in kwargs and kwargs["sudo"] is not False: + self.write_sudo_rules(name, kwargs["sudo"]) # Import SSH keys - if 'ssh_authorized_keys' in kwargs: + if "ssh_authorized_keys" in kwargs: # Try to handle this in a smart manner. - keys = kwargs['ssh_authorized_keys'] + keys = kwargs["ssh_authorized_keys"] if isinstance(keys, str): keys = [keys] elif isinstance(keys, dict): keys = list(keys.values()) if keys is not None: if not isinstance(keys, (tuple, list, set)): - LOG.warning("Invalid type '%s' detected for" - " 'ssh_authorized_keys', expected list," - " string, dict, or set.", type(keys)) + LOG.warning( + "Invalid type '%s' detected for" + " 'ssh_authorized_keys', expected list," + " string, dict, or set.", + type(keys), + ) keys = [] else: keys = set(keys) or [] ssh_util.setup_user_keys(set(keys), name) - if 'ssh_redirect_user' in kwargs: - cloud_keys = kwargs.get('cloud_public_ssh_keys', []) + if "ssh_redirect_user" in kwargs: + cloud_keys = kwargs.get("cloud_public_ssh_keys", []) if not cloud_keys: LOG.warning( - 'Unable to disable SSH logins for %s given' - ' ssh_redirect_user: %s. No cloud public-keys present.', - name, kwargs['ssh_redirect_user']) + "Unable to disable SSH logins for %s given" + " ssh_redirect_user: %s. No cloud public-keys present.", + name, + kwargs["ssh_redirect_user"], + ) else: - redirect_user = kwargs['ssh_redirect_user'] + redirect_user = kwargs["ssh_redirect_user"] disable_option = ssh_util.DISABLE_USER_OPTS - disable_option = disable_option.replace('$USER', redirect_user) - disable_option = disable_option.replace('$DISABLE_USER', name) + disable_option = disable_option.replace("$USER", redirect_user) + disable_option = disable_option.replace("$DISABLE_USER", name) ssh_util.setup_user_keys( - set(cloud_keys), name, options=disable_option) + set(cloud_keys), name, options=disable_option + ) return True def lock_passwd(self, name): @@ -643,36 +678,36 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): Lock the password of a user, i.e., disable password logins """ # passwd must use short '-l' due to SLES11 lacking long form '--lock' - lock_tools = (['passwd', '-l', name], ['usermod', '--lock', name]) + lock_tools = (["passwd", "-l", name], ["usermod", "--lock", name]) try: cmd = next(tool for tool in lock_tools if subp.which(tool[0])) except StopIteration as e: - raise RuntimeError(( + 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: - util.logexc(LOG, 'Failed to disable password for user %s', name) + util.logexc(LOG, "Failed to disable password for user %s", name) raise e def expire_passwd(self, user): try: - subp.subp(['passwd', '--expire', user]) + subp.subp(["passwd", "--expire", user]) except Exception as e: util.logexc(LOG, "Failed to set 'expire' for %s", user) raise e def set_passwd(self, user, passwd, hashed=False): - pass_string = '%s:%s' % (user, passwd) - cmd = ['chpasswd'] + pass_string = "%s:%s" % (user, passwd) + cmd = ["chpasswd"] if hashed: # Need to use the short option name '-e' instead of '--encrypted' # (which would be more descriptive) since SLES 11 doesn't know # about long names. - cmd.append('-e') + cmd.append("-e") try: subp.subp(cmd, pass_string, logstring="chpasswd for %s" % user) @@ -682,10 +717,10 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): return True - def ensure_sudo_dir(self, path, sudo_base='/etc/sudoers'): + def ensure_sudo_dir(self, path, sudo_base="/etc/sudoers"): # Ensure the dir is included and that # it actually exists as a directory - sudoers_contents = '' + sudoers_contents = "" base_exists = False if os.path.exists(sudo_base): sudoers_contents = util.load_file(sudo_base) @@ -706,15 +741,23 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): if not found_include: try: if not base_exists: - lines = [('# See sudoers(5) for more information' - ' on "#include" directives:'), '', - util.make_header(base="added"), - "#includedir %s" % (path), ''] + lines = [ + "# See sudoers(5) for more information" + ' on "#include" directives:', + "", + util.make_header(base="added"), + "#includedir %s" % (path), + "", + ] sudoers_contents = "\n".join(lines) util.write_file(sudo_base, sudoers_contents, 0o440) else: - lines = ['', util.make_header(base="added"), - "#includedir %s" % (path), ''] + lines = [ + "", + util.make_header(base="added"), + "#includedir %s" % (path), + "", + ] sudoers_contents = "\n".join(lines) util.append_file(sudo_base, sudoers_contents) LOG.debug("Added '#includedir %s' to %s", path, sudo_base) @@ -728,7 +771,7 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): sudo_file = self.ci_sudoers_fn lines = [ - '', + "", "# User rules for %s" % user, ] if isinstance(rules, (list, tuple)): @@ -761,9 +804,9 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): raise e def create_group(self, name, members=None): - group_add_cmd = ['groupadd', name] + group_add_cmd = ["groupadd", name] if util.system_is_snappy(): - group_add_cmd.append('--extrausers') + group_add_cmd.append("--extrausers") if not members: members = [] @@ -781,11 +824,15 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): if len(members) > 0: for member in members: if not util.is_user(member): - LOG.warning("Unable to add group member '%s' to group '%s'" - "; user does not exist.", member, name) + LOG.warning( + "Unable to add group member '%s' to group '%s'" + "; user does not exist.", + member, + name, + ) continue - subp.subp(['usermod', '-a', '-G', name, member]) + subp.subp(["usermod", "-a", "-G", name, member]) LOG.info("Added user '%s' to group '%s'", member, name) def shutdown_command(self, *, mode, delay, message): @@ -812,23 +859,25 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): May raise ProcessExecutionError """ init_cmd = self.init_cmd - if self.uses_systemd() or 'systemctl' in init_cmd: - init_cmd = ['systemctl'] - cmds = {'stop': ['stop', service], - 'start': ['start', service], - 'enable': ['enable', service], - 'restart': ['restart', service], - 'reload': ['reload-or-restart', service], - 'try-reload': ['reload-or-try-restart', service], - } + if self.uses_systemd() or "systemctl" in init_cmd: + init_cmd = ["systemctl"] + cmds = { + "stop": ["stop", service], + "start": ["start", service], + "enable": ["enable", service], + "restart": ["restart", service], + "reload": ["reload-or-restart", service], + "try-reload": ["reload-or-try-restart", service], + } else: - cmds = {'stop': [service, 'stop'], - 'start': [service, 'start'], - 'enable': [service, 'start'], - 'restart': [service, 'restart'], - 'reload': [service, 'restart'], - 'try-reload': [service, 'restart'], - } + cmds = { + "stop": [service, "stop"], + "start": [service, "start"], + "enable": [service, "start"], + "restart": [service, "restart"], + "reload": [service, "restart"], + "try-reload": [service, "restart"], + } cmd = list(init_cmd) + list(cmds[action]) return subp.subp(cmd, capture=True) @@ -919,27 +968,25 @@ def _sanitize_mirror_url(url: str): # This is an IP address, not a hostname, so no need to apply the # transformations lambda hostname: None if net.is_ip_address(hostname) else hostname, - # Encode with IDNA to get the correct characters (as `bytes`), then # decode with ASCII so we return a `str` - lambda hostname: hostname.encode('idna').decode('ascii'), - + lambda hostname: hostname.encode("idna").decode("ascii"), # Replace any unacceptable characters with "-" - lambda hostname: ''.join( + lambda hostname: "".join( c if c in acceptable_chars else "-" for c in hostname ), - # Drop leading/trailing hyphens from each part of the hostname - lambda hostname: '.'.join( - part.strip('-') for part in hostname.split('.') + lambda hostname: ".".join( + part.strip("-") for part in hostname.split(".") ), ] return _apply_hostname_transformations_to_url(url, transformations) -def _get_package_mirror_info(mirror_info, data_source=None, - mirror_filter=util.search_for_mirror): +def _get_package_mirror_info( + mirror_info, data_source=None, mirror_filter=util.search_for_mirror +): # given a arch specific 'mirror_info' entry (from package_mirrors) # search through the 'search' entries, and fallback appropriately # return a dict with only {name: mirror} entries. @@ -948,7 +995,7 @@ def _get_package_mirror_info(mirror_info, data_source=None, subst = {} if data_source and data_source.availability_zone: - subst['availability_zone'] = data_source.availability_zone + subst["availability_zone"] = data_source.availability_zone # ec2 availability zones are named cc-direction-[0-9][a-d] (us-east-1b) # the region is us-east-1. so region = az[0:-1] @@ -956,18 +1003,18 @@ def _get_package_mirror_info(mirror_info, data_source=None, ec2_region = data_source.availability_zone[0:-1] if ALLOW_EC2_MIRRORS_ON_NON_AWS_INSTANCE_TYPES: - subst['ec2_region'] = "%s" % ec2_region + subst["ec2_region"] = "%s" % ec2_region elif data_source.platform_type == "ec2": - subst['ec2_region'] = "%s" % ec2_region + subst["ec2_region"] = "%s" % ec2_region if data_source and data_source.region: - subst['region'] = data_source.region + subst["region"] = data_source.region results = {} - for (name, mirror) in mirror_info.get('failsafe', {}).items(): + for (name, mirror) in mirror_info.get("failsafe", {}).items(): results[name] = mirror - for (name, searchlist) in mirror_info.get('search', {}).items(): + for (name, searchlist) in mirror_info.get("search", {}).items(): mirrors = [] for tmpl in searchlist: try: @@ -1001,17 +1048,20 @@ def _get_arch_package_mirror_info(package_mirrors, arch): def fetch(name): - locs, looked_locs = importer.find_module(name, ['', __name__], ['Distro']) + locs, looked_locs = importer.find_module(name, ["", __name__], ["Distro"]) if not locs: - raise ImportError("No distribution found for distro %s (searched %s)" - % (name, looked_locs)) + raise ImportError( + "No distribution found for distro %s (searched %s)" + % (name, looked_locs) + ) mod = importer.import_module(locs[0]) - cls = getattr(mod, 'Distro') + cls = getattr(mod, "Distro") return cls -def set_etc_timezone(tz, tz_file=None, tz_conf="/etc/timezone", - tz_local="/etc/localtime"): +def set_etc_timezone( + tz, tz_file=None, tz_conf="/etc/timezone", tz_local="/etc/localtime" +): util.write_file(tz_conf, str(tz).rstrip() + "\n") # This ensures that the correct tz will be used for the system if tz_local and tz_file: @@ -1028,7 +1078,7 @@ def set_etc_timezone(tz, tz_file=None, tz_conf="/etc/timezone", def uses_systemd(): try: - res = os.lstat('/run/systemd/system') + res = os.lstat("/run/systemd/system") return stat.S_ISDIR(res.st_mode) except Exception: return False diff --git a/cloudinit/distros/almalinux.py b/cloudinit/distros/almalinux.py index edb3165d..3dc0a342 100644 --- a/cloudinit/distros/almalinux.py +++ b/cloudinit/distros/almalinux.py @@ -6,4 +6,5 @@ from cloudinit.distros import rhel class Distro(rhel.Distro): pass + # vi: ts=4 expandtab diff --git a/cloudinit/distros/alpine.py b/cloudinit/distros/alpine.py index e82965fd..3d7d4891 100644 --- a/cloudinit/distros/alpine.py +++ b/cloudinit/distros/alpine.py @@ -6,13 +6,8 @@ # # This file is part of cloud-init. See LICENSE file for license information. -from cloudinit import distros -from cloudinit import helpers -from cloudinit import subp -from cloudinit import util - +from cloudinit import distros, helpers, subp, util from cloudinit.distros.parsers.hostname import HostnameConf - from cloudinit.settings import PER_INSTANCE NETWORK_FILE_HEADER = """\ @@ -26,12 +21,11 @@ NETWORK_FILE_HEADER = """\ class Distro(distros.Distro): - init_cmd = ['rc-service'] # init scripts + init_cmd = ["rc-service"] # init scripts locale_conf_fn = "/etc/profile.d/locale.sh" network_conf_fn = "/etc/network/interfaces" renderer_configs = { - "eni": {"eni_path": network_conf_fn, - "eni_header": NETWORK_FILE_HEADER} + "eni": {"eni_path": network_conf_fn, "eni_header": NETWORK_FILE_HEADER} } def __init__(self, name, cfg, paths): @@ -40,13 +34,13 @@ class Distro(distros.Distro): # calls from repeatly happening (when they # should only happen say once per instance...) self._runner = helpers.Runners(paths) - self.default_locale = 'C.UTF-8' - self.osfamily = 'alpine' - cfg['ssh_svcname'] = 'sshd' + self.default_locale = "C.UTF-8" + self.osfamily = "alpine" + cfg["ssh_svcname"] = "sshd" def get_locale(self): """The default locale for Alpine Linux is different than - cloud-init's DataSource default. + cloud-init's DataSource default. """ return self.default_locale @@ -71,7 +65,7 @@ class Distro(distros.Distro): def install_packages(self, pkglist): self.update_package_sources() - self.package_command('add', pkgs=pkglist) + self.package_command("add", pkgs=pkglist) def _write_hostname(self, hostname, filename): conf = None @@ -82,7 +76,7 @@ class Distro(distros.Distro): except IOError: pass if not conf: - conf = HostnameConf('') + conf = HostnameConf("") conf.set_hostname(hostname) util.write_file(filename, str(conf), 0o644) @@ -116,7 +110,7 @@ class Distro(distros.Distro): if pkgs is None: pkgs = [] - cmd = ['apk'] + cmd = ["apk"] # Redirect output cmd.append("--quiet") @@ -128,28 +122,32 @@ class Distro(distros.Distro): if command: cmd.append(command) - if command == 'upgrade': + if command == "upgrade": cmd.extend(["--update-cache", "--available"]) - pkglist = util.expand_package_list('%s-%s', pkgs) + pkglist = util.expand_package_list("%s-%s", pkgs) cmd.extend(pkglist) # Allow the output of this to flow outwards (ie not be captured) subp.subp(cmd, capture=False) def update_package_sources(self): - self._runner.run("update-sources", self.package_command, - ["update"], freq=PER_INSTANCE) + self._runner.run( + "update-sources", + self.package_command, + ["update"], + freq=PER_INSTANCE, + ) @property def preferred_ntp_clients(self): """Allow distro to determine the preferred ntp client list""" if not self._preferred_ntp_clients: - self._preferred_ntp_clients = ['chrony', 'ntp'] + self._preferred_ntp_clients = ["chrony", "ntp"] return self._preferred_ntp_clients - def shutdown_command(self, mode='poweroff', delay='now', message=None): + def shutdown_command(self, mode="poweroff", delay="now", message=None): # called from cc_power_state_change.load_power_state # Alpine has halt/poweroff/reboot, with the following specifics: # - we use them rather than the generic "shutdown" @@ -163,7 +161,7 @@ class Distro(distros.Distro): # halt/poweroff/reboot commands take seconds rather than minutes. if delay == "now": # Alpine's commands do not understand "now". - command += ['0'] + command += ["0"] else: try: command.append(str(int(delay) * 60)) @@ -175,4 +173,5 @@ class Distro(distros.Distro): return command + # vi: ts=4 expandtab diff --git a/cloudinit/distros/amazon.py b/cloudinit/distros/amazon.py index 5fcec952..a3573547 100644 --- a/cloudinit/distros/amazon.py +++ b/cloudinit/distros/amazon.py @@ -14,7 +14,6 @@ from cloudinit.distros import rhel class Distro(rhel.Distro): - def update_package_sources(self): return None diff --git a/cloudinit/distros/arch.py b/cloudinit/distros/arch.py index 3c5bbb38..0bdfef83 100644 --- a/cloudinit/distros/arch.py +++ b/cloudinit/distros/arch.py @@ -4,32 +4,29 @@ # # This file is part of cloud-init. See LICENSE file for license information. -from cloudinit import distros -from cloudinit import helpers -from cloudinit import log as logging -from cloudinit import util -from cloudinit import subp +import os +from cloudinit import distros, helpers +from cloudinit import log as logging +from cloudinit import subp, util from cloudinit.distros import net_util from cloudinit.distros.parsers.hostname import HostnameConf - from cloudinit.net.renderers import RendererNotFoundError - from cloudinit.settings import PER_INSTANCE -import os - LOG = logging.getLogger(__name__) class Distro(distros.Distro): locale_gen_fn = "/etc/locale.gen" network_conf_dir = "/etc/netctl" - init_cmd = ['systemctl'] # init scripts + init_cmd = ["systemctl"] # init scripts renderer_configs = { - "netplan": {"netplan_path": "/etc/netplan/50-cloud-init.yaml", - "netplan_header": "# generated by cloud-init\n", - "postcmds": True} + "netplan": { + "netplan_path": "/etc/netplan/50-cloud-init.yaml", + "netplan_header": "# generated by cloud-init\n", + "postcmds": True, + } } def __init__(self, name, cfg, paths): @@ -38,28 +35,31 @@ class Distro(distros.Distro): # calls from repeatly happening (when they # should only happen say once per instance...) self._runner = helpers.Runners(paths) - self.osfamily = 'arch' - cfg['ssh_svcname'] = 'sshd' + self.osfamily = "arch" + cfg["ssh_svcname"] = "sshd" def apply_locale(self, locale, out_fn=None): if out_fn is not None and out_fn != "/etc/locale.conf": - LOG.warning("Invalid locale_configfile %s, only supported " - "value is /etc/locale.conf", out_fn) + LOG.warning( + "Invalid locale_configfile %s, only supported " + "value is /etc/locale.conf", + out_fn, + ) lines = [ util.make_header(), # Hard-coding the charset isn't ideal, but there is no other way. - '%s UTF-8' % (locale), + "%s UTF-8" % (locale), "", ] util.write_file(self.locale_gen_fn, "\n".join(lines)) - subp.subp(['locale-gen'], capture=False) + subp.subp(["locale-gen"], capture=False) # In the future systemd can handle locale-gen stuff: # https://github.com/systemd/systemd/pull/9864 - subp.subp(['localectl', 'set-locale', locale], capture=False) + subp.subp(["localectl", "set-locale", locale], capture=False) def install_packages(self, pkglist): self.update_package_sources() - self.package_command('', pkgs=pkglist) + self.package_command("", pkgs=pkglist) def _write_network_state(self, network_state): try: @@ -70,32 +70,42 @@ class Distro(distros.Distro): def _write_network(self, settings): entries = net_util.translate_network(settings) - LOG.debug("Translated ubuntu style network settings %s into %s", - settings, entries) + LOG.debug( + "Translated ubuntu style network settings %s into %s", + settings, + entries, + ) return _render_network( - entries, resolv_conf=self.resolve_conf_fn, + entries, + resolv_conf=self.resolve_conf_fn, conf_dir=self.network_conf_dir, - enable_func=self._enable_interface) + enable_func=self._enable_interface, + ) def _enable_interface(self, device_name): - cmd = ['netctl', 'reenable', device_name] + cmd = ["netctl", "reenable", device_name] try: (_out, err) = subp.subp(cmd) if len(err): - LOG.warning("Running %s resulted in stderr output: %s", - cmd, err) + LOG.warning( + "Running %s resulted in stderr output: %s", cmd, err + ) except subp.ProcessExecutionError: util.logexc(LOG, "Running interface command %s failed", cmd) def _bring_up_interface(self, device_name): - cmd = ['netctl', 'restart', device_name] - LOG.debug("Attempting to run bring up interface %s using command %s", - device_name, cmd) + cmd = ["netctl", "restart", device_name] + LOG.debug( + "Attempting to run bring up interface %s using command %s", + device_name, + cmd, + ) try: (_out, err) = subp.subp(cmd) if len(err): - LOG.warning("Running %s resulted in stderr output: %s", - cmd, err) + LOG.warning( + "Running %s resulted in stderr output: %s", cmd, err + ) return True except subp.ProcessExecutionError: util.logexc(LOG, "Running interface command %s failed", cmd) @@ -110,7 +120,7 @@ class Distro(distros.Distro): except IOError: pass if not conf: - conf = HostnameConf('') + conf = HostnameConf("") conf.set_hostname(hostname) util.write_file(filename, str(conf), omode="w", mode=0o644) @@ -137,13 +147,17 @@ class Distro(distros.Distro): # hostname (inetutils) isn't installed per default on arch, so we use # hostnamectl which is installed per default (systemd). def _apply_hostname(self, hostname): - LOG.debug("Non-persistently setting the system hostname to %s", - hostname) + LOG.debug( + "Non-persistently setting the system hostname to %s", hostname + ) try: - subp.subp(['hostnamectl', '--transient', 'set-hostname', hostname]) + subp.subp(["hostnamectl", "--transient", "set-hostname", hostname]) except subp.ProcessExecutionError: - util.logexc(LOG, "Failed to non-persistently adjust the system " - "hostname to %s", hostname) + util.logexc( + LOG, + "Failed to non-persistently adjust the system hostname to %s", + hostname, + ) def set_timezone(self, tz): distros.set_etc_timezone(tz=tz, tz_file=self._find_tz_file(tz)) @@ -152,7 +166,7 @@ class Distro(distros.Distro): if pkgs is None: pkgs = [] - cmd = ['pacman', "-Sy", "--quiet", "--noconfirm"] + cmd = ["pacman", "-Sy", "--quiet", "--noconfirm"] # Redirect output if args and isinstance(args, str): @@ -165,19 +179,25 @@ class Distro(distros.Distro): if command: cmd.append(command) - pkglist = util.expand_package_list('%s-%s', pkgs) + pkglist = util.expand_package_list("%s-%s", pkgs) cmd.extend(pkglist) # Allow the output of this to flow outwards (ie not be captured) subp.subp(cmd, capture=False) def update_package_sources(self): - self._runner.run("update-sources", self.package_command, - ["-y"], freq=PER_INSTANCE) - - -def _render_network(entries, target="/", conf_dir="etc/netctl", - resolv_conf="etc/resolv.conf", enable_func=None): + self._runner.run( + "update-sources", self.package_command, ["-y"], freq=PER_INSTANCE + ) + + +def _render_network( + entries, + target="/", + conf_dir="etc/netctl", + resolv_conf="etc/resolv.conf", + enable_func=None, +): """Render the translate_network format into netctl files in target. Paths will be rendered under target. """ @@ -188,29 +208,27 @@ def _render_network(entries, target="/", conf_dir="etc/netctl", conf_dir = subp.target_path(target, conf_dir) for (dev, info) in entries.items(): - if dev == 'lo': + if dev == "lo": # no configuration should be rendered for 'lo' continue devs.append(dev) net_fn = os.path.join(conf_dir, dev) net_cfg = { - 'Connection': 'ethernet', - 'Interface': dev, - 'IP': info.get('bootproto'), - 'Address': "%s/%s" % (info.get('address'), - info.get('netmask')), - 'Gateway': info.get('gateway'), - 'DNS': info.get('dns-nameservers', []), + "Connection": "ethernet", + "Interface": dev, + "IP": info.get("bootproto"), + "Address": "%s/%s" % (info.get("address"), info.get("netmask")), + "Gateway": info.get("gateway"), + "DNS": info.get("dns-nameservers", []), } util.write_file(net_fn, convert_netctl(net_cfg)) - if enable_func and info.get('auto'): + if enable_func and info.get("auto"): enable_func(dev) - if 'dns-nameservers' in info: - nameservers.extend(info['dns-nameservers']) + if "dns-nameservers" in info: + nameservers.extend(info["dns-nameservers"]) if nameservers: - util.write_file(resolv_conf, - convert_resolv_conf(nameservers)) + util.write_file(resolv_conf, convert_resolv_conf(nameservers)) return devs @@ -227,17 +245,18 @@ def convert_netctl(settings): if val is None: val = "" elif isinstance(val, (tuple, list)): - val = "(" + ' '.join("'%s'" % v for v in val) + ")" + val = "(" + " ".join("'%s'" % v for v in val) + ")" result.append("%s=%s\n" % (key, val)) - return ''.join(result) + return "".join(result) def convert_resolv_conf(settings): """Returns a settings string formatted for resolv.conf.""" - result = '' + result = "" if isinstance(settings, list): for ns in settings: - result = result + 'nameserver %s\n' % ns + result = result + "nameserver %s\n" % ns return result + # vi: ts=4 expandtab diff --git a/cloudinit/distros/bsd.py b/cloudinit/distros/bsd.py index c2fc1e0b..1b4498b3 100644 --- a/cloudinit/distros/bsd.py +++ b/cloudinit/distros/bsd.py @@ -1,12 +1,10 @@ import platform -from cloudinit import distros -from cloudinit.distros import bsd_utils -from cloudinit import helpers +from cloudinit import distros, helpers from cloudinit import log as logging -from cloudinit import net -from cloudinit import subp -from cloudinit import util +from cloudinit import net, subp, util +from cloudinit.distros import bsd_utils + from .networking import BSDNetworking LOG = logging.getLogger(__name__) @@ -14,12 +12,12 @@ LOG = logging.getLogger(__name__) class BSD(distros.Distro): networking_cls = BSDNetworking - hostname_conf_fn = '/etc/rc.conf' + hostname_conf_fn = "/etc/rc.conf" rc_conf_fn = "/etc/rc.conf" # This differs from the parent Distro class, which has -P for # poweroff. - shutdown_options_map = {'halt': '-H', 'poweroff': '-p', 'reboot': '-r'} + shutdown_options_map = {"halt": "-H", "poweroff": "-p", "reboot": "-r"} # Set in BSD distro subclasses group_add_cmd_prefix = [] @@ -35,7 +33,7 @@ class BSD(distros.Distro): # calls from repeatly happening (when they # should only happen say once per instance...) self._runner = helpers.Runners(paths) - cfg['ssh_svcname'] = 'sshd' + cfg["ssh_svcname"] = "sshd" self.osfamily = platform.system().lower() def _read_system_hostname(self): @@ -43,13 +41,13 @@ class BSD(distros.Distro): return (self.hostname_conf_fn, sys_hostname) def _read_hostname(self, filename, default=None): - return bsd_utils.get_rc_config_value('hostname') + return bsd_utils.get_rc_config_value("hostname") def _get_add_member_to_group_cmd(self, member_name, group_name): - raise NotImplementedError('Return list cmd to add member to group') + raise NotImplementedError("Return list cmd to add member to group") def _write_hostname(self, hostname, filename): - bsd_utils.set_rc_config_value('hostname', hostname, fn='/etc/rc.conf') + bsd_utils.set_rc_config_value("hostname", hostname, fn="/etc/rc.conf") def create_group(self, name, members=None): if util.is_group(name): @@ -66,45 +64,55 @@ class BSD(distros.Distro): members = [] for member in members: if not util.is_user(member): - LOG.warning("Unable to add group member '%s' to group '%s'" - "; user does not exist.", member, name) + LOG.warning( + "Unable to add group member '%s' to group '%s'" + "; user does not exist.", + member, + name, + ) continue try: subp.subp(self._get_add_member_to_group_cmd(member, name)) LOG.info("Added user '%s' to group '%s'", member, name) except Exception: - util.logexc(LOG, "Failed to add user '%s' to group '%s'", - member, name) + util.logexc( + LOG, "Failed to add user '%s' to group '%s'", member, name + ) def generate_fallback_config(self): - nconf = {'config': [], 'version': 1} + nconf = {"config": [], "version": 1} for mac, name in net.get_interfaces_by_mac().items(): - nconf['config'].append( - {'type': 'physical', 'name': name, - 'mac_address': mac, 'subnets': [{'type': 'dhcp'}]}) + nconf["config"].append( + { + "type": "physical", + "name": name, + "mac_address": mac, + "subnets": [{"type": "dhcp"}], + } + ) return nconf def install_packages(self, pkglist): self.update_package_sources() - self.package_command('install', pkgs=pkglist) + self.package_command("install", pkgs=pkglist) def _get_pkg_cmd_environ(self): """Return environment vars used in *BSD package_command operations""" - raise NotImplementedError('BSD subclasses return a dict of env vars') + raise NotImplementedError("BSD subclasses return a dict of env vars") def package_command(self, command, args=None, pkgs=None): if pkgs is None: pkgs = [] - if command == 'install': + if command == "install": cmd = self.pkg_cmd_install_prefix - elif command == 'remove': + elif command == "remove": cmd = self.pkg_cmd_remove_prefix - elif command == 'update': + elif command == "update": if not self.pkg_cmd_update_prefix: return cmd = self.pkg_cmd_update_prefix - elif command == 'upgrade': + elif command == "upgrade": if not self.pkg_cmd_upgrade_prefix: return cmd = self.pkg_cmd_upgrade_prefix @@ -114,7 +122,7 @@ class BSD(distros.Distro): elif args and isinstance(args, list): cmd.extend(args) - pkglist = util.expand_package_list('%s-%s', pkgs) + pkglist = util.expand_package_list("%s-%s", pkgs) cmd.extend(pkglist) # Allow the output of this to flow outwards (ie not be captured) @@ -124,7 +132,7 @@ class BSD(distros.Distro): distros.set_etc_timezone(tz=tz, tz_file=self._find_tz_file(tz)) def apply_locale(self, locale, out_fn=None): - LOG.debug('Cannot set the locale.') + LOG.debug("Cannot set the locale.") def apply_network_config_names(self, netconfig): - LOG.debug('Cannot rename network interface.') + LOG.debug("Cannot rename network interface.") diff --git a/cloudinit/distros/bsd_utils.py b/cloudinit/distros/bsd_utils.py index 079d0d53..00cd0662 100644 --- a/cloudinit/distros/bsd_utils.py +++ b/cloudinit/distros/bsd_utils.py @@ -18,31 +18,31 @@ def _unquote(value): return value -def get_rc_config_value(key, fn='/etc/rc.conf'): - key_prefix = '{}='.format(key) +def get_rc_config_value(key, fn="/etc/rc.conf"): + key_prefix = "{}=".format(key) for line in util.load_file(fn).splitlines(): if line.startswith(key_prefix): - value = line.replace(key_prefix, '') + value = line.replace(key_prefix, "") return _unquote(value) -def set_rc_config_value(key, value, fn='/etc/rc.conf'): +def set_rc_config_value(key, value, fn="/etc/rc.conf"): lines = [] done = False value = shlex.quote(value) original_content = util.load_file(fn) for line in original_content.splitlines(): - if '=' in line: - k, v = line.split('=', 1) + if "=" in line: + k, v = line.split("=", 1) if k == key: v = value done = True - lines.append('='.join([k, v])) + lines.append("=".join([k, v])) else: lines.append(line) if not done: - lines.append('='.join([key, value])) - new_content = '\n'.join(lines) + '\n' + lines.append("=".join([key, value])) + new_content = "\n".join(lines) + "\n" if new_content != original_content: util.write_file(fn, new_content) diff --git a/cloudinit/distros/centos.py b/cloudinit/distros/centos.py index edb3165d..3dc0a342 100644 --- a/cloudinit/distros/centos.py +++ b/cloudinit/distros/centos.py @@ -6,4 +6,5 @@ from cloudinit.distros import rhel class Distro(rhel.Distro): pass + # vi: ts=4 expandtab diff --git a/cloudinit/distros/cloudlinux.py b/cloudinit/distros/cloudlinux.py index edb3165d..3dc0a342 100644 --- a/cloudinit/distros/cloudlinux.py +++ b/cloudinit/distros/cloudlinux.py @@ -6,4 +6,5 @@ from cloudinit.distros import rhel class Distro(rhel.Distro): pass + # vi: ts=4 expandtab diff --git a/cloudinit/distros/debian.py b/cloudinit/distros/debian.py index b2af0866..0105a383 100644 --- a/cloudinit/distros/debian.py +++ b/cloudinit/distros/debian.py @@ -11,25 +11,25 @@ import fcntl import os import time -from cloudinit import distros -from cloudinit import helpers +from cloudinit import distros, helpers from cloudinit import log as logging -from cloudinit import subp -from cloudinit import util - +from cloudinit import subp, util from cloudinit.distros.parsers.hostname import HostnameConf - from cloudinit.settings import PER_INSTANCE LOG = logging.getLogger(__name__) APT_LOCK_WAIT_TIMEOUT = 30 -APT_GET_COMMAND = ('apt-get', '--option=Dpkg::Options::=--force-confold', - '--option=Dpkg::options::=--force-unsafe-io', - '--assume-yes', '--quiet') +APT_GET_COMMAND = ( + "apt-get", + "--option=Dpkg::Options::=--force-confold", + "--option=Dpkg::options::=--force-unsafe-io", + "--assume-yes", + "--quiet", +) APT_GET_WRAPPER = { - 'command': 'eatmydata', - 'enabled': 'auto', + "command": "eatmydata", + "enabled": "auto", } NETWORK_FILE_HEADER = """\ @@ -50,10 +50,10 @@ LOCALE_CONF_FN = "/etc/default/locale" # More context: # https://github.com/canonical/cloud-init/pull/1034#issuecomment-986971376 APT_LOCK_FILES = [ - '/var/lib/dpkg/lock-frontend', - '/var/lib/dpkg/lock', - '/var/cache/apt/archives/lock', - '/var/lib/apt/lists/lock', + "/var/lib/dpkg/lock-frontend", + "/var/lib/dpkg/lock", + "/var/cache/apt/archives/lock", + "/var/lib/apt/lists/lock", ] @@ -61,14 +61,18 @@ class Distro(distros.Distro): hostname_conf_fn = "/etc/hostname" network_conf_fn = { "eni": "/etc/network/interfaces.d/50-cloud-init", - "netplan": "/etc/netplan/50-cloud-init.yaml" + "netplan": "/etc/netplan/50-cloud-init.yaml", } renderer_configs = { - "eni": {"eni_path": network_conf_fn["eni"], - "eni_header": NETWORK_FILE_HEADER}, - "netplan": {"netplan_path": network_conf_fn["netplan"], - "netplan_header": NETWORK_FILE_HEADER, - "postcmds": True} + "eni": { + "eni_path": network_conf_fn["eni"], + "eni_header": NETWORK_FILE_HEADER, + }, + "netplan": { + "netplan_path": network_conf_fn["netplan"], + "netplan_header": NETWORK_FILE_HEADER, + "postcmds": True, + }, } def __init__(self, name, cfg, paths): @@ -77,8 +81,8 @@ class Distro(distros.Distro): # calls from repeatly happening (when they # should only happen say once per instance...) self._runner = helpers.Runners(paths) - self.osfamily = 'debian' - self.default_locale = 'en_US.UTF-8' + self.osfamily = "debian" + self.default_locale = "en_US.UTF-8" self.system_locale = None def get_locale(self): @@ -89,25 +93,29 @@ class Distro(distros.Distro): self.system_locale = read_system_locale() # Return system_locale setting if valid, else use default locale - return (self.system_locale if self.system_locale else - self.default_locale) + return ( + self.system_locale if self.system_locale else self.default_locale + ) - def apply_locale(self, locale, out_fn=None, keyname='LANG'): + def apply_locale(self, locale, out_fn=None, keyname="LANG"): """Apply specified locale to system, regenerate if specified locale - differs from system default.""" + differs from system default.""" if not out_fn: out_fn = LOCALE_CONF_FN if not locale: - raise ValueError('Failed to provide locale value.') + raise ValueError("Failed to provide locale value.") # Only call locale regeneration if needed # Update system locale config with specified locale if needed distro_locale = self.get_locale() conf_fn_exists = os.path.exists(out_fn) sys_locale_unset = False if self.system_locale else True - need_regen = (locale.lower() != distro_locale.lower() or - not conf_fn_exists or sys_locale_unset) + need_regen = ( + locale.lower() != distro_locale.lower() + or not conf_fn_exists + or sys_locale_unset + ) need_conf = not conf_fn_exists or need_regen or sys_locale_unset if need_regen: @@ -115,7 +123,10 @@ class Distro(distros.Distro): else: LOG.debug( "System has '%s=%s' requested '%s', skipping regeneration.", - keyname, self.system_locale, locale) + keyname, + self.system_locale, + locale, + ) if need_conf: update_locale_conf(locale, out_fn, keyname=keyname) @@ -124,7 +135,7 @@ class Distro(distros.Distro): def install_packages(self, pkglist): self.update_package_sources() - self.package_command('install', pkgs=pkglist) + self.package_command("install", pkgs=pkglist) def _write_network_state(self, network_state): _maybe_remove_legacy_eth0() @@ -139,7 +150,7 @@ class Distro(distros.Distro): except IOError: pass if not conf: - conf = HostnameConf('') + conf = HostnameConf("") conf.set_hostname(hostname) util.write_file(filename, str(conf), 0o644) @@ -181,7 +192,7 @@ class Distro(distros.Distro): if not os.path.exists(lock): # Only wait for lock files that already exist continue - with open(lock, 'w') as handle: + with open(lock, "w") as handle: try: fcntl.lockf(handle, fcntl.LOCK_EX | fcntl.LOCK_NB) except OSError: @@ -197,17 +208,17 @@ class Distro(distros.Distro): subp_kwargs: kwargs to pass to subp """ start_time = time.time() - LOG.debug('Waiting for apt lock') + LOG.debug("Waiting for apt lock") while time.time() - start_time < timeout: if not self._apt_lock_available(): time.sleep(1) continue - LOG.debug('apt lock available') + LOG.debug("apt lock available") try: # Allow the output of this to flow outwards (not be captured) log_msg = "apt-%s [%s]" % ( short_cmd, - ' '.join(subp_kwargs['args']) + " ".join(subp_kwargs["args"]), ) return util.log_time( logfunc=LOG.debug, @@ -228,9 +239,9 @@ class Distro(distros.Distro): # error received. If the lock is unavailable, just keep waiting if self._apt_lock_available(): raise - LOG.debug('Another process holds apt lock. Waiting...') + LOG.debug("Another process holds apt lock. Waiting...") time.sleep(1) - raise TimeoutError('Could not get apt lock') + raise TimeoutError("Could not get apt lock") def package_command(self, command, args=None, pkgs=None): """Run the given package command. @@ -247,12 +258,13 @@ class Distro(distros.Distro): e = os.environ.copy() # See: http://manpages.ubuntu.com/manpages/xenial/man7/debconf.7.html - e['DEBIAN_FRONTEND'] = 'noninteractive' + e["DEBIAN_FRONTEND"] = "noninteractive" wcfg = self.get_option("apt_get_wrapper", APT_GET_WRAPPER) cmd = _get_wrapper_prefix( - wcfg.get('command', APT_GET_WRAPPER['command']), - wcfg.get('enabled', APT_GET_WRAPPER['enabled'])) + wcfg.get("command", APT_GET_WRAPPER["command"]), + wcfg.get("enabled", APT_GET_WRAPPER["enabled"]), + ) cmd.extend(list(self.get_option("apt_get_command", APT_GET_COMMAND))) @@ -263,22 +275,27 @@ class Distro(distros.Distro): subcmd = command if command == "upgrade": - subcmd = self.get_option("apt_get_upgrade_subcommand", - "dist-upgrade") + subcmd = self.get_option( + "apt_get_upgrade_subcommand", "dist-upgrade" + ) cmd.append(subcmd) - pkglist = util.expand_package_list('%s=%s', pkgs) + pkglist = util.expand_package_list("%s=%s", pkgs) cmd.extend(pkglist) self._wait_for_apt_command( short_cmd=command, - subp_kwargs={'args': cmd, 'env': e, 'capture': False} + subp_kwargs={"args": cmd, "env": e, "capture": False}, ) def update_package_sources(self): - self._runner.run("update-sources", self.package_command, - ["update"], freq=PER_INSTANCE) + self._runner.run( + "update-sources", + self.package_command, + ["update"], + freq=PER_INSTANCE, + ) def get_primary_arch(self): return util.get_dpkg_architecture() @@ -288,9 +305,9 @@ def _get_wrapper_prefix(cmd, mode): if isinstance(cmd, str): cmd = [str(cmd)] - if (util.is_true(mode) or - (str(mode).lower() == "auto" and cmd[0] and - subp.which(cmd[0]))): + if util.is_true(mode) or ( + str(mode).lower() == "auto" and cmd[0] and subp.which(cmd[0]) + ): return cmd else: return [] @@ -298,13 +315,13 @@ def _get_wrapper_prefix(cmd, mode): def _maybe_remove_legacy_eth0(path="/etc/network/interfaces.d/eth0.cfg"): """Ubuntu cloud images previously included a 'eth0.cfg' that had - hard coded content. That file would interfere with the rendered - configuration if it was present. + hard coded content. That file would interfere with the rendered + configuration if it was present. - if the file does not exist do nothing. - If the file exists: - - with known content, remove it and warn - - with unknown content, leave it and warn + if the file does not exist do nothing. + If the file exists: + - with known content, remove it and warn + - with unknown content, leave it and warn """ if not os.path.exists(path): @@ -314,24 +331,25 @@ def _maybe_remove_legacy_eth0(path="/etc/network/interfaces.d/eth0.cfg"): try: contents = util.load_file(path) known_contents = ["auto eth0", "iface eth0 inet dhcp"] - lines = [f.strip() for f in contents.splitlines() - if not f.startswith("#")] + lines = [ + f.strip() for f in contents.splitlines() if not f.startswith("#") + ] if lines == known_contents: util.del_file(path) msg = "removed %s with known contents" % path else: - msg = (bmsg + " '%s' exists with user configured content." % path) + msg = bmsg + " '%s' exists with user configured content." % path except Exception: msg = bmsg + " %s exists, but could not be read." % path LOG.warning(msg) -def read_system_locale(sys_path=LOCALE_CONF_FN, keyname='LANG'): +def read_system_locale(sys_path=LOCALE_CONF_FN, keyname="LANG"): """Read system default locale setting, if present""" sys_val = "" if not sys_path: - raise ValueError('Invalid path: %s' % sys_path) + raise ValueError("Invalid path: %s" % sys_path) if os.path.exists(sys_path): locale_content = util.load_file(sys_path) @@ -341,16 +359,22 @@ def read_system_locale(sys_path=LOCALE_CONF_FN, keyname='LANG'): return sys_val -def update_locale_conf(locale, sys_path, keyname='LANG'): +def update_locale_conf(locale, sys_path, keyname="LANG"): """Update system locale config""" - LOG.debug('Updating %s with locale setting %s=%s', - sys_path, keyname, locale) + LOG.debug( + "Updating %s with locale setting %s=%s", sys_path, keyname, locale + ) subp.subp( - ['update-locale', '--locale-file=' + sys_path, - '%s=%s' % (keyname, locale)], capture=False) + [ + "update-locale", + "--locale-file=" + sys_path, + "%s=%s" % (keyname, locale), + ], + capture=False, + ) -def regenerate_locale(locale, sys_path, keyname='LANG'): +def regenerate_locale(locale, sys_path, keyname="LANG"): """ Run locale-gen for the provided locale and set the default system variable `keyname` appropriately in the provided `sys_path`. @@ -361,13 +385,13 @@ def regenerate_locale(locale, sys_path, keyname='LANG'): # C # C.UTF-8 # POSIX - if locale.lower() in ['c', 'c.utf-8', 'posix']: - LOG.debug('%s=%s does not require rengeneration', keyname, locale) + if locale.lower() in ["c", "c.utf-8", "posix"]: + LOG.debug("%s=%s does not require rengeneration", keyname, locale) return # finally, trigger regeneration - LOG.debug('Generating locales for %s', locale) - subp.subp(['locale-gen', locale], capture=False) + LOG.debug("Generating locales for %s", locale) + subp.subp(["locale-gen", locale], capture=False) # vi: ts=4 expandtab diff --git a/cloudinit/distros/dragonflybsd.py b/cloudinit/distros/dragonflybsd.py index 2d825518..0d02bee0 100644 --- a/cloudinit/distros/dragonflybsd.py +++ b/cloudinit/distros/dragonflybsd.py @@ -6,7 +6,7 @@ import cloudinit.distros.freebsd class Distro(cloudinit.distros.freebsd.Distro): - home_dir = '/home' + home_dir = "/home" # vi: ts=4 expandtab diff --git a/cloudinit/distros/eurolinux.py b/cloudinit/distros/eurolinux.py index edb3165d..3dc0a342 100644 --- a/cloudinit/distros/eurolinux.py +++ b/cloudinit/distros/eurolinux.py @@ -6,4 +6,5 @@ from cloudinit.distros import rhel class Distro(rhel.Distro): pass + # vi: ts=4 expandtab diff --git a/cloudinit/distros/fedora.py b/cloudinit/distros/fedora.py index 0fe1fbca..39203225 100644 --- a/cloudinit/distros/fedora.py +++ b/cloudinit/distros/fedora.py @@ -14,4 +14,5 @@ from cloudinit.distros import rhel class Distro(rhel.Distro): pass + # vi: ts=4 expandtab diff --git a/cloudinit/distros/freebsd.py b/cloudinit/distros/freebsd.py index d94a52b8..513abdc2 100644 --- a/cloudinit/distros/freebsd.py +++ b/cloudinit/distros/freebsd.py @@ -10,8 +10,7 @@ from io import StringIO import cloudinit.distros.bsd from cloudinit import log as logging -from cloudinit import subp -from cloudinit import util +from cloudinit import subp, util from cloudinit.settings import PER_INSTANCE LOG = logging.getLogger(__name__) @@ -24,41 +23,41 @@ class Distro(cloudinit.distros.bsd.BSD): (N.B. DragonFlyBSD inherits from this class.) """ - usr_lib_exec = '/usr/local/lib' - login_conf_fn = '/etc/login.conf' - login_conf_fn_bak = '/etc/login.conf.orig' - ci_sudoers_fn = '/usr/local/etc/sudoers.d/90-cloud-init-users' - group_add_cmd_prefix = ['pw', 'group', 'add'] + usr_lib_exec = "/usr/local/lib" + login_conf_fn = "/etc/login.conf" + login_conf_fn_bak = "/etc/login.conf.orig" + ci_sudoers_fn = "/usr/local/etc/sudoers.d/90-cloud-init-users" + group_add_cmd_prefix = ["pw", "group", "add"] pkg_cmd_install_prefix = ["pkg", "install"] pkg_cmd_remove_prefix = ["pkg", "remove"] pkg_cmd_update_prefix = ["pkg", "update"] pkg_cmd_upgrade_prefix = ["pkg", "upgrade"] prefer_fqdn = True # See rc.conf(5) in FreeBSD - home_dir = '/usr/home' + home_dir = "/usr/home" def _get_add_member_to_group_cmd(self, member_name, group_name): - return ['pw', 'usermod', '-n', member_name, '-G', group_name] + return ["pw", "usermod", "-n", member_name, "-G", group_name] def add_user(self, name, **kwargs): if util.is_user(name): LOG.info("User %s already exists, skipping.", name) return False - pw_useradd_cmd = ['pw', 'useradd', '-n', name] - log_pw_useradd_cmd = ['pw', 'useradd', '-n', name] + pw_useradd_cmd = ["pw", "useradd", "-n", name] + log_pw_useradd_cmd = ["pw", "useradd", "-n", name] pw_useradd_opts = { - "homedir": '-d', - "gecos": '-c', - "primary_group": '-g', - "groups": '-G', - "shell": '-s', - "inactive": '-E', + "homedir": "-d", + "gecos": "-c", + "primary_group": "-g", + "groups": "-G", + "shell": "-s", + "inactive": "-E", } pw_useradd_flags = { - "no_user_group": '--no-user-group', - "system": '--system', - "no_log_init": '--no-log-init', + "no_user_group": "--no-user-group", + "system": "--system", + "no_log_init": "--no-log-init", } for key, val in kwargs.items(): @@ -69,17 +68,19 @@ class Distro(cloudinit.distros.bsd.BSD): pw_useradd_cmd.append(pw_useradd_flags[key]) log_pw_useradd_cmd.append(pw_useradd_flags[key]) - if 'no_create_home' in kwargs or 'system' in kwargs: - pw_useradd_cmd.append('-d/nonexistent') - log_pw_useradd_cmd.append('-d/nonexistent') + if "no_create_home" in kwargs or "system" in kwargs: + pw_useradd_cmd.append("-d/nonexistent") + log_pw_useradd_cmd.append("-d/nonexistent") else: - pw_useradd_cmd.append('-d{home_dir}/{name}'.format( - home_dir=self.home_dir, name=name)) - pw_useradd_cmd.append('-m') - log_pw_useradd_cmd.append('-d{home_dir}/{name}'.format( - home_dir=self.home_dir, name=name)) + pw_useradd_cmd.append( + "-d{home_dir}/{name}".format(home_dir=self.home_dir, name=name) + ) + pw_useradd_cmd.append("-m") + log_pw_useradd_cmd.append( + "-d{home_dir}/{name}".format(home_dir=self.home_dir, name=name) + ) - log_pw_useradd_cmd.append('-m') + log_pw_useradd_cmd.append("-m") # Run the command LOG.info("Adding user %s", name) @@ -90,13 +91,13 @@ class Distro(cloudinit.distros.bsd.BSD): raise # Set the password if it is provided # For security consideration, only hashed passwd is assumed - passwd_val = kwargs.get('passwd', None) + passwd_val = kwargs.get("passwd", None) if passwd_val is not None: self.set_passwd(name, passwd_val, hashed=True) def expire_passwd(self, user): try: - subp.subp(['pw', 'usermod', user, '-p', '01-Jan-1970']) + subp.subp(["pw", "usermod", user, "-p", "01-Jan-1970"]) except Exception: util.logexc(LOG, "Failed to set pw expiration for %s", user) raise @@ -108,15 +109,18 @@ class Distro(cloudinit.distros.bsd.BSD): hash_opt = "-h" try: - subp.subp(['pw', 'usermod', user, hash_opt, '0'], - data=passwd, logstring="chpasswd for %s" % user) + subp.subp( + ["pw", "usermod", user, hash_opt, "0"], + data=passwd, + logstring="chpasswd for %s" % user, + ) except Exception: util.logexc(LOG, "Failed to set password for %s", user) raise def lock_passwd(self, name): try: - subp.subp(['pw', 'usermod', name, '-h', '-']) + subp.subp(["pw", "usermod", name, "-h", "-"]) except Exception: util.logexc(LOG, "Failed to lock user %s", name) raise @@ -125,8 +129,9 @@ class Distro(cloudinit.distros.bsd.BSD): # Adjust the locales value to the new value newconf = StringIO() for line in util.load_file(self.login_conf_fn).splitlines(): - newconf.write(re.sub(r'^default:', - r'default:lang=%s:' % locale, line)) + newconf.write( + re.sub(r"^default:", r"default:lang=%s:" % locale, line) + ) newconf.write("\n") # Make a backup of login.conf. @@ -137,15 +142,16 @@ class Distro(cloudinit.distros.bsd.BSD): try: LOG.debug("Running cap_mkdb for %s", locale) - subp.subp(['cap_mkdb', self.login_conf_fn]) + subp.subp(["cap_mkdb", self.login_conf_fn]) except subp.ProcessExecutionError: # cap_mkdb failed, so restore the backup. util.logexc(LOG, "Failed to apply locale %s", locale) try: util.copy(self.login_conf_fn_bak, self.login_conf_fn) except IOError: - util.logexc(LOG, "Failed to restore %s backup", - self.login_conf_fn) + util.logexc( + LOG, "Failed to restore %s backup", self.login_conf_fn + ) def apply_network_config_names(self, netconfig): # This is handled by the freebsd network renderer. It writes in @@ -157,13 +163,16 @@ class Distro(cloudinit.distros.bsd.BSD): def _get_pkg_cmd_environ(self): """Return environment vars used in *BSD package_command operations""" e = os.environ.copy() - e['ASSUME_ALWAYS_YES'] = 'YES' + e["ASSUME_ALWAYS_YES"] = "YES" return e def update_package_sources(self): self._runner.run( - "update-sources", self.package_command, - ["update"], freq=PER_INSTANCE) + "update-sources", + self.package_command, + ["update"], + freq=PER_INSTANCE, + ) # vi: ts=4 expandtab diff --git a/cloudinit/distros/gentoo.py b/cloudinit/distros/gentoo.py index 1be76dc8..1384a682 100644 --- a/cloudinit/distros/gentoo.py +++ b/cloudinit/distros/gentoo.py @@ -6,25 +6,21 @@ # # This file is part of cloud-init. See LICENSE file for license information. -from cloudinit import distros -from cloudinit import helpers +from cloudinit import distros, helpers from cloudinit import log as logging -from cloudinit import subp -from cloudinit import util - +from cloudinit import subp, util from cloudinit.distros import net_util from cloudinit.distros.parsers.hostname import HostnameConf - from cloudinit.settings import PER_INSTANCE LOG = logging.getLogger(__name__) class Distro(distros.Distro): - locale_conf_fn = '/etc/locale.gen' - network_conf_fn = '/etc/conf.d/net' - hostname_conf_fn = '/etc/conf.d/hostname' - init_cmd = ['rc-service'] # init scripts + locale_conf_fn = "/etc/locale.gen" + network_conf_fn = "/etc/conf.d/net" + hostname_conf_fn = "/etc/conf.d/hostname" + init_cmd = ["rc-service"] # init scripts def __init__(self, name, cfg, paths): distros.Distro.__init__(self, name, cfg, paths) @@ -32,14 +28,14 @@ class Distro(distros.Distro): # calls from repeatly happening (when they # should only happen say once per instance...) self._runner = helpers.Runners(paths) - self.osfamily = 'gentoo' + self.osfamily = "gentoo" # Fix sshd restarts - cfg['ssh_svcname'] = '/etc/init.d/sshd' + cfg["ssh_svcname"] = "/etc/init.d/sshd" def apply_locale(self, locale, out_fn=None): if not out_fn: out_fn = self.locale_conf_fn - subp.subp(['locale-gen', '-G', locale], capture=False) + subp.subp(["locale-gen", "-G", locale], capture=False) # "" provides trailing newline during join lines = [ util.make_header(), @@ -50,79 +46,97 @@ class Distro(distros.Distro): def install_packages(self, pkglist): self.update_package_sources() - self.package_command('', pkgs=pkglist) + self.package_command("", pkgs=pkglist) def _write_network(self, settings): entries = net_util.translate_network(settings) - LOG.debug("Translated ubuntu style network settings %s into %s", - settings, entries) + LOG.debug( + "Translated ubuntu style network settings %s into %s", + settings, + entries, + ) dev_names = entries.keys() nameservers = [] for (dev, info) in entries.items(): - if 'dns-nameservers' in info: - nameservers.extend(info['dns-nameservers']) - if dev == 'lo': + if "dns-nameservers" in info: + nameservers.extend(info["dns-nameservers"]) + if dev == "lo": continue - net_fn = self.network_conf_fn + '.' + dev - dns_nameservers = info.get('dns-nameservers') + net_fn = self.network_conf_fn + "." + dev + dns_nameservers = info.get("dns-nameservers") if isinstance(dns_nameservers, (list, tuple)): - dns_nameservers = str(tuple(dns_nameservers)).replace(',', '') + dns_nameservers = str(tuple(dns_nameservers)).replace(",", "") # eth0, {'auto': True, 'ipv6': {}, 'bootproto': 'dhcp'} # lo, {'dns-nameservers': ['10.0.1.3'], 'ipv6': {}, 'auto': True} - results = '' - if info.get('bootproto') == 'dhcp': + results = "" + if info.get("bootproto") == "dhcp": results += 'config_{name}="dhcp"'.format(name=dev) else: results += ( 'config_{name}="{ip_address} netmask {netmask}"\n' 'mac_{name}="{hwaddr}"\n' - ).format(name=dev, ip_address=info.get('address'), - netmask=info.get('netmask'), - hwaddr=info.get('hwaddress')) - results += 'routes_{name}="default via {gateway}"\n'.format( + ).format( name=dev, - gateway=info.get('gateway') + ip_address=info.get("address"), + netmask=info.get("netmask"), + hwaddr=info.get("hwaddress"), + ) + results += 'routes_{name}="default via {gateway}"\n'.format( + name=dev, gateway=info.get("gateway") ) - if info.get('dns-nameservers'): + if info.get("dns-nameservers"): results += 'dns_servers_{name}="{dnsservers}"\n'.format( - name=dev, - dnsservers=dns_nameservers) + name=dev, dnsservers=dns_nameservers + ) util.write_file(net_fn, results) self._create_network_symlink(dev) - if info.get('auto'): - cmd = ['rc-update', 'add', 'net.{name}'.format(name=dev), - 'default'] + if info.get("auto"): + cmd = [ + "rc-update", + "add", + "net.{name}".format(name=dev), + "default", + ] try: (_out, err) = subp.subp(cmd) if len(err): - LOG.warning("Running %s resulted in stderr output: %s", - cmd, err) + LOG.warning( + "Running %s resulted in stderr output: %s", + cmd, + err, + ) except subp.ProcessExecutionError: - util.logexc(LOG, "Running interface command %s failed", - cmd) + util.logexc( + LOG, "Running interface command %s failed", cmd + ) if nameservers: - util.write_file(self.resolve_conf_fn, - convert_resolv_conf(nameservers)) + util.write_file( + self.resolve_conf_fn, convert_resolv_conf(nameservers) + ) return dev_names @staticmethod def _create_network_symlink(interface_name): - file_path = '/etc/init.d/net.{name}'.format(name=interface_name) + file_path = "/etc/init.d/net.{name}".format(name=interface_name) if not util.is_link(file_path): - util.sym_link('/etc/init.d/net.lo', file_path) + util.sym_link("/etc/init.d/net.lo", file_path) def _bring_up_interface(self, device_name): - cmd = ['/etc/init.d/net.%s' % device_name, 'restart'] - LOG.debug("Attempting to run bring up interface %s using command %s", - device_name, cmd) + cmd = ["/etc/init.d/net.%s" % device_name, "restart"] + LOG.debug( + "Attempting to run bring up interface %s using command %s", + device_name, + cmd, + ) try: (_out, err) = subp.subp(cmd) if len(err): - LOG.warning("Running %s resulted in stderr output: %s", - cmd, err) + LOG.warning( + "Running %s resulted in stderr output: %s", cmd, err + ) return True except subp.ProcessExecutionError: util.logexc(LOG, "Running interface command %s failed", cmd) @@ -131,20 +145,21 @@ class Distro(distros.Distro): def _bring_up_interfaces(self, device_names): use_all = False for d in device_names: - if d == 'all': + if d == "all": use_all = True if use_all: # Grab device names from init scripts - cmd = ['ls', '/etc/init.d/net.*'] + cmd = ["ls", "/etc/init.d/net.*"] try: (_out, err) = subp.subp(cmd) if len(err): - LOG.warning("Running %s resulted in stderr output: %s", - cmd, err) + LOG.warning( + "Running %s resulted in stderr output: %s", cmd, err + ) except subp.ProcessExecutionError: util.logexc(LOG, "Running interface command %s failed", cmd) return False - devices = [x.split('.')[2] for x in _out.split(' ')] + devices = [x.split(".")[2] for x in _out.split(" ")] return distros.Distro._bring_up_interfaces(self, devices) else: return distros.Distro._bring_up_interfaces(self, device_names) @@ -158,7 +173,7 @@ class Distro(distros.Distro): except IOError: pass if not conf: - conf = HostnameConf('') + conf = HostnameConf("") # Many distro's format is the hostname by itself, and that is the # way HostnameConf works but gentoo expects it to be in @@ -194,7 +209,7 @@ class Distro(distros.Distro): if pkgs is None: pkgs = [] - cmd = list('emerge') + cmd = list("emerge") # Redirect output cmd.append("--quiet") @@ -206,23 +221,28 @@ class Distro(distros.Distro): if command: cmd.append(command) - pkglist = util.expand_package_list('%s-%s', pkgs) + pkglist = util.expand_package_list("%s-%s", pkgs) cmd.extend(pkglist) # Allow the output of this to flow outwards (ie not be captured) subp.subp(cmd, capture=False) def update_package_sources(self): - self._runner.run("update-sources", self.package_command, - ["-u", "world"], freq=PER_INSTANCE) + self._runner.run( + "update-sources", + self.package_command, + ["-u", "world"], + freq=PER_INSTANCE, + ) def convert_resolv_conf(settings): """Returns a settings string formatted for resolv.conf.""" - result = '' + result = "" if isinstance(settings, list): for ns in settings: - result += 'nameserver %s\n' % ns + result += "nameserver %s\n" % ns return result + # vi: ts=4 expandtab diff --git a/cloudinit/distros/miraclelinux.py b/cloudinit/distros/miraclelinux.py index c7753387..3dc0a342 100644 --- a/cloudinit/distros/miraclelinux.py +++ b/cloudinit/distros/miraclelinux.py @@ -5,4 +5,6 @@ from cloudinit.distros import rhel class Distro(rhel.Distro): pass + + # vi: ts=4 expandtab diff --git a/cloudinit/distros/net_util.py b/cloudinit/distros/net_util.py index edfcd99d..e37fb19b 100644 --- a/cloudinit/distros/net_util.py +++ b/cloudinit/distros/net_util.py @@ -68,7 +68,9 @@ # } from cloudinit.net.network_state import ( - net_prefix_to_ipv4_mask, mask_and_ipv4_to_bcast_addr) + mask_and_ipv4_to_bcast_addr, + net_prefix_to_ipv4_mask, +) def translate_network(settings): @@ -86,7 +88,7 @@ def translate_network(settings): ifaces = [] consume = {} for (cmd, args) in entries: - if cmd == 'iface': + if cmd == "iface": if consume: ifaces.append(consume) consume = {} @@ -96,19 +98,19 @@ def translate_network(settings): # Check if anything left over to consume absorb = False for (cmd, args) in consume.items(): - if cmd == 'iface': + if cmd == "iface": absorb = True if absorb: ifaces.append(consume) # Now translate real_ifaces = {} for info in ifaces: - if 'iface' not in info: + if "iface" not in info: continue - iface_details = info['iface'].split(None) + iface_details = info["iface"].split(None) # Check if current device *may* have an ipv6 IP use_ipv6 = False - if 'inet6' in iface_details: + if "inet6" in iface_details: use_ipv6 = True dev_name = None if len(iface_details) >= 1: @@ -118,55 +120,54 @@ def translate_network(settings): if not dev_name: continue iface_info = {} - iface_info['ipv6'] = {} + iface_info["ipv6"] = {} if len(iface_details) >= 3: proto_type = iface_details[2].strip().lower() # Seems like this can be 'loopback' which we don't # really care about - if proto_type in ['dhcp', 'static']: - iface_info['bootproto'] = proto_type + if proto_type in ["dhcp", "static"]: + iface_info["bootproto"] = proto_type # These can just be copied over if use_ipv6: - for k in ['address', 'gateway']: + for k in ["address", "gateway"]: if k in info: val = info[k].strip().lower() if val: - iface_info['ipv6'][k] = val + iface_info["ipv6"][k] = val else: - for k in ['netmask', 'address', 'gateway', 'broadcast']: + for k in ["netmask", "address", "gateway", "broadcast"]: if k in info: val = info[k].strip().lower() if val: iface_info[k] = val # handle static ip configurations using # ipaddress/prefix-length format - if 'address' in iface_info: - if 'netmask' not in iface_info: + if "address" in iface_info: + if "netmask" not in iface_info: # check if the address has a network prefix - addr, _, prefix = iface_info['address'].partition('/') + addr, _, prefix = iface_info["address"].partition("/") if prefix: - iface_info['netmask'] = ( - net_prefix_to_ipv4_mask(prefix)) - iface_info['address'] = addr + iface_info["netmask"] = net_prefix_to_ipv4_mask(prefix) + iface_info["address"] = addr # if we set the netmask, we also can set the broadcast - iface_info['broadcast'] = ( - mask_and_ipv4_to_bcast_addr( - iface_info['netmask'], addr)) + iface_info["broadcast"] = mask_and_ipv4_to_bcast_addr( + iface_info["netmask"], addr + ) # Name server info provided?? - if 'dns-nameservers' in info: - iface_info['dns-nameservers'] = info['dns-nameservers'].split() + if "dns-nameservers" in info: + iface_info["dns-nameservers"] = info["dns-nameservers"].split() # Name server search info provided?? - if 'dns-search' in info: - iface_info['dns-search'] = info['dns-search'].split() + if "dns-search" in info: + iface_info["dns-search"] = info["dns-search"].split() # Is any mac address spoofing going on?? - if 'hwaddress' in info: - hw_info = info['hwaddress'].lower().strip() + if "hwaddress" in info: + hw_info = info["hwaddress"].lower().strip() hw_split = hw_info.split(None, 1) - if len(hw_split) == 2 and hw_split[0].startswith('ether'): + if len(hw_split) == 2 and hw_split[0].startswith("ether"): hw_addr = hw_split[1] if hw_addr: - iface_info['hwaddress'] = hw_addr + iface_info["hwaddress"] = hw_addr # If ipv6 is enabled, device will have multiple IPs, so we need to # update the dictionary instead of overwriting it... if dev_name in real_ifaces: @@ -179,13 +180,14 @@ def translate_network(settings): if not args: continue dev_name = args[0].strip().lower() - if cmd == 'auto': + if cmd == "auto": # Seems like auto can be like 'auto eth0 eth0:1' so just get the # first part out as the device name if dev_name in real_ifaces: - real_ifaces[dev_name]['auto'] = True - if cmd == 'iface' and 'inet6' in args: - real_ifaces[dev_name]['inet6'] = True + real_ifaces[dev_name]["auto"] = True + if cmd == "iface" and "inet6" in args: + real_ifaces[dev_name]["inet6"] = True return real_ifaces + # vi: ts=4 expandtab diff --git a/cloudinit/distros/netbsd.py b/cloudinit/distros/netbsd.py index f1a9b182..9c38ae51 100644 --- a/cloudinit/distros/netbsd.py +++ b/cloudinit/distros/netbsd.py @@ -8,8 +8,7 @@ import platform import cloudinit.distros.bsd from cloudinit import log as logging -from cloudinit import subp -from cloudinit import util +from cloudinit import subp, util LOG = logging.getLogger(__name__) @@ -21,42 +20,42 @@ class NetBSD(cloudinit.distros.bsd.BSD): (N.B. OpenBSD inherits from this class.) """ - ci_sudoers_fn = '/usr/pkg/etc/sudoers.d/90-cloud-init-users' + ci_sudoers_fn = "/usr/pkg/etc/sudoers.d/90-cloud-init-users" group_add_cmd_prefix = ["groupadd"] def __init__(self, name, cfg, paths): super().__init__(name, cfg, paths) if os.path.exists("/usr/pkg/bin/pkgin"): - self.pkg_cmd_install_prefix = ['pkgin', '-y', 'install'] - self.pkg_cmd_remove_prefix = ['pkgin', '-y', 'remove'] - self.pkg_cmd_update_prefix = ['pkgin', '-y', 'update'] - self.pkg_cmd_upgrade_prefix = ['pkgin', '-y', 'full-upgrade'] + self.pkg_cmd_install_prefix = ["pkgin", "-y", "install"] + self.pkg_cmd_remove_prefix = ["pkgin", "-y", "remove"] + self.pkg_cmd_update_prefix = ["pkgin", "-y", "update"] + self.pkg_cmd_upgrade_prefix = ["pkgin", "-y", "full-upgrade"] else: - self.pkg_cmd_install_prefix = ['pkg_add', '-U'] - self.pkg_cmd_remove_prefix = ['pkg_delete'] + self.pkg_cmd_install_prefix = ["pkg_add", "-U"] + self.pkg_cmd_remove_prefix = ["pkg_delete"] def _get_add_member_to_group_cmd(self, member_name, group_name): - return ['usermod', '-G', group_name, member_name] + return ["usermod", "-G", group_name, member_name] def add_user(self, name, **kwargs): if util.is_user(name): LOG.info("User %s already exists, skipping.", name) return False - adduser_cmd = ['useradd'] - log_adduser_cmd = ['useradd'] + adduser_cmd = ["useradd"] + log_adduser_cmd = ["useradd"] adduser_opts = { - "homedir": '-d', - "gecos": '-c', - "primary_group": '-g', - "groups": '-G', - "shell": '-s', + "homedir": "-d", + "gecos": "-c", + "primary_group": "-g", + "groups": "-G", + "shell": "-s", } adduser_flags = { - "no_user_group": '--no-user-group', - "system": '--system', - "no_log_init": '--no-log-init', + "no_user_group": "--no-user-group", + "system": "--system", + "no_log_init": "--no-log-init", } for key, val in kwargs.items(): @@ -67,9 +66,9 @@ class NetBSD(cloudinit.distros.bsd.BSD): adduser_cmd.append(adduser_flags[key]) log_adduser_cmd.append(adduser_flags[key]) - if 'no_create_home' not in kwargs or 'system' not in kwargs: - adduser_cmd += ['-m'] - log_adduser_cmd += ['-m'] + if "no_create_home" not in kwargs or "system" not in kwargs: + adduser_cmd += ["-m"] + log_adduser_cmd += ["-m"] adduser_cmd += [name] log_adduser_cmd += [name] @@ -83,29 +82,28 @@ class NetBSD(cloudinit.distros.bsd.BSD): raise # Set the password if it is provided # For security consideration, only hashed passwd is assumed - passwd_val = kwargs.get('passwd', None) + passwd_val = kwargs.get("passwd", None) if passwd_val is not None: self.set_passwd(name, passwd_val, hashed=True) def set_passwd(self, user, passwd, hashed=False): if hashed: hashed_pw = passwd - elif not hasattr(crypt, 'METHOD_BLOWFISH'): + elif not hasattr(crypt, "METHOD_BLOWFISH"): # crypt.METHOD_BLOWFISH comes with Python 3.7 which is available # on NetBSD 7 and 8. - LOG.error(( - 'Cannot set non-encrypted password for user %s. ' - 'Python >= 3.7 is required.'), user) + LOG.error( + "Cannot set non-encrypted password for user %s. " + "Python >= 3.7 is required.", + user, + ) return else: method = crypt.METHOD_BLOWFISH # pylint: disable=E1101 - hashed_pw = crypt.crypt( - passwd, - crypt.mksalt(method) - ) + hashed_pw = crypt.crypt(passwd, crypt.mksalt(method)) try: - subp.subp(['usermod', '-p', hashed_pw, user]) + subp.subp(["usermod", "-p", hashed_pw, user]) except Exception: util.logexc(LOG, "Failed to set password for %s", user) raise @@ -113,40 +111,42 @@ class NetBSD(cloudinit.distros.bsd.BSD): def force_passwd_change(self, user): try: - subp.subp(['usermod', '-F', user]) + subp.subp(["usermod", "-F", user]) except Exception: util.logexc(LOG, "Failed to set pw expiration for %s", user) raise def lock_passwd(self, name): try: - subp.subp(['usermod', '-C', 'yes', name]) + subp.subp(["usermod", "-C", "yes", name]) except Exception: util.logexc(LOG, "Failed to lock user %s", name) raise def unlock_passwd(self, name): try: - subp.subp(['usermod', '-C', 'no', name]) + subp.subp(["usermod", "-C", "no", name]) except Exception: util.logexc(LOG, "Failed to unlock user %s", name) raise def apply_locale(self, locale, out_fn=None): - LOG.debug('Cannot set the locale.') + LOG.debug("Cannot set the locale.") def apply_network_config_names(self, netconfig): - LOG.debug('NetBSD cannot rename network interface.') + LOG.debug("NetBSD cannot rename network interface.") def _get_pkg_cmd_environ(self): """Return env vars used in NetBSD package_command operations""" os_release = platform.release() os_arch = platform.machine() e = os.environ.copy() - e['PKG_PATH'] = ( - 'http://cdn.netbsd.org/pub/pkgsrc/' - 'packages/NetBSD/%s/%s/All' - ) % (os_arch, os_release) + e[ + "PKG_PATH" + ] = "http://cdn.netbsd.org/pub/pkgsrc/packages/NetBSD/%s/%s/All" % ( + os_arch, + os_release, + ) return e def update_package_sources(self): @@ -156,4 +156,5 @@ class NetBSD(cloudinit.distros.bsd.BSD): class Distro(NetBSD): pass + # vi: ts=4 expandtab diff --git a/cloudinit/distros/networking.py b/cloudinit/distros/networking.py index c291196a..e18a48ca 100644 --- a/cloudinit/distros/networking.py +++ b/cloudinit/distros/networking.py @@ -2,9 +2,7 @@ import abc import logging import os -from cloudinit import subp -from cloudinit import net, util - +from cloudinit import net, subp, util LOG = logging.getLogger(__name__) @@ -73,7 +71,8 @@ class Networking(metaclass=abc.ABCMeta): def get_interfaces_by_mac(self) -> dict: return net.get_interfaces_by_mac( - blacklist_drivers=self.blacklist_drivers) + blacklist_drivers=self.blacklist_drivers + ) def get_master(self, devname: DeviceName): return net.get_master(devname) @@ -225,7 +224,7 @@ class LinuxNetworking(Networking): def try_set_link_up(self, devname: DeviceName) -> bool: """Try setting the link to up explicitly and return if it is up. - Not guaranteed to bring the interface up. The caller is expected to - add wait times before retrying.""" - subp.subp(['ip', 'link', 'set', devname, 'up']) + Not guaranteed to bring the interface up. The caller is expected to + add wait times before retrying.""" + subp.subp(["ip", "link", "set", devname, "up"]) return self.is_up(devname) diff --git a/cloudinit/distros/openEuler.py b/cloudinit/distros/openEuler.py index edb3165d..3dc0a342 100644 --- a/cloudinit/distros/openEuler.py +++ b/cloudinit/distros/openEuler.py @@ -6,4 +6,5 @@ from cloudinit.distros import rhel class Distro(rhel.Distro): pass + # vi: ts=4 expandtab diff --git a/cloudinit/distros/openbsd.py b/cloudinit/distros/openbsd.py index 720c9cf3..ccdb8799 100644 --- a/cloudinit/distros/openbsd.py +++ b/cloudinit/distros/openbsd.py @@ -7,28 +7,27 @@ import platform import cloudinit.distros.netbsd from cloudinit import log as logging -from cloudinit import subp -from cloudinit import util +from cloudinit import subp, util LOG = logging.getLogger(__name__) class Distro(cloudinit.distros.netbsd.NetBSD): - hostname_conf_fn = '/etc/myname' + hostname_conf_fn = "/etc/myname" def _read_hostname(self, filename, default=None): return util.load_file(self.hostname_conf_fn) def _write_hostname(self, hostname, filename): - content = hostname + '\n' + content = hostname + "\n" util.write_file(self.hostname_conf_fn, content) def _get_add_member_to_group_cmd(self, member_name, group_name): - return ['usermod', '-G', group_name, member_name] + return ["usermod", "-G", group_name, member_name] def lock_passwd(self, name): try: - subp.subp(['usermod', '-p', '*', name]) + subp.subp(["usermod", "-p", "*", name]) except Exception: util.logexc(LOG, "Failed to lock user %s", name) raise @@ -41,11 +40,10 @@ class Distro(cloudinit.distros.netbsd.NetBSD): os_release = platform.release() os_arch = platform.machine() e = os.environ.copy() - e['PKG_PATH'] = ( - 'ftp://ftp.openbsd.org/pub/OpenBSD/{os_release}/' - 'packages/{os_arch}/').format( - os_arch=os_arch, os_release=os_release - ) + e["PKG_PATH"] = ( + "ftp://ftp.openbsd.org/pub/OpenBSD/{os_release}/" + "packages/{os_arch}/" + ).format(os_arch=os_arch, os_release=os_release) return e diff --git a/cloudinit/distros/opensuse.py b/cloudinit/distros/opensuse.py index 2a7497cc..00ed1514 100644 --- a/cloudinit/distros/opensuse.py +++ b/cloudinit/distros/opensuse.py @@ -8,68 +8,61 @@ # # This file is part of cloud-init. See LICENSE file for license information. -from cloudinit import distros - -from cloudinit.distros.parsers.hostname import HostnameConf - -from cloudinit import helpers -from cloudinit import subp -from cloudinit import util - +from cloudinit import distros, helpers, subp, util from cloudinit.distros import rhel_util as rhutil +from cloudinit.distros.parsers.hostname import HostnameConf from cloudinit.settings import PER_INSTANCE class Distro(distros.Distro): - clock_conf_fn = '/etc/sysconfig/clock' - hostname_conf_fn = '/etc/HOSTNAME' - init_cmd = ['service'] - locale_conf_fn = '/etc/sysconfig/language' - network_conf_fn = '/etc/sysconfig/network/config' - network_script_tpl = '/etc/sysconfig/network/ifcfg-%s' - route_conf_tpl = '/etc/sysconfig/network/ifroute-%s' - systemd_hostname_conf_fn = '/etc/hostname' - systemd_locale_conf_fn = '/etc/locale.conf' - tz_local_fn = '/etc/localtime' + clock_conf_fn = "/etc/sysconfig/clock" + hostname_conf_fn = "/etc/HOSTNAME" + init_cmd = ["service"] + locale_conf_fn = "/etc/sysconfig/language" + network_conf_fn = "/etc/sysconfig/network/config" + network_script_tpl = "/etc/sysconfig/network/ifcfg-%s" + route_conf_tpl = "/etc/sysconfig/network/ifroute-%s" + systemd_hostname_conf_fn = "/etc/hostname" + systemd_locale_conf_fn = "/etc/locale.conf" + tz_local_fn = "/etc/localtime" renderer_configs = { - 'sysconfig': { - 'control': 'etc/sysconfig/network/config', - 'flavor': 'suse', - 'iface_templates': '%(base)s/network/ifcfg-%(name)s', - 'netrules_path': ( - 'etc/udev/rules.d/85-persistent-net-cloud-init.rules'), - 'route_templates': { - 'ipv4': '%(base)s/network/ifroute-%(name)s', - 'ipv6': '%(base)s/network/ifroute-%(name)s', - } + "sysconfig": { + "control": "etc/sysconfig/network/config", + "flavor": "suse", + "iface_templates": "%(base)s/network/ifcfg-%(name)s", + "netrules_path": ( + "etc/udev/rules.d/85-persistent-net-cloud-init.rules" + ), + "route_templates": { + "ipv4": "%(base)s/network/ifroute-%(name)s", + "ipv6": "%(base)s/network/ifroute-%(name)s", + }, } } def __init__(self, name, cfg, paths): distros.Distro.__init__(self, name, cfg, paths) self._runner = helpers.Runners(paths) - self.osfamily = 'suse' - cfg['ssh_svcname'] = 'sshd' + self.osfamily = "suse" + cfg["ssh_svcname"] = "sshd" if self.uses_systemd(): - self.init_cmd = ['systemctl'] - cfg['ssh_svcname'] = 'sshd.service' + self.init_cmd = ["systemctl"] + cfg["ssh_svcname"] = "sshd.service" def apply_locale(self, locale, out_fn=None): if self.uses_systemd(): if not out_fn: out_fn = self.systemd_locale_conf_fn - locale_cfg = {'LANG': locale} + locale_cfg = {"LANG": locale} else: if not out_fn: out_fn = self.locale_conf_fn - locale_cfg = {'RC_LANG': locale} + locale_cfg = {"RC_LANG": locale} rhutil.update_sysconfig_file(out_fn, locale_cfg) def install_packages(self, pkglist): self.package_command( - 'install', - args='--auto-agree-with-licenses', - pkgs=pkglist + "install", args="--auto-agree-with-licenses", pkgs=pkglist ) def package_command(self, command, args=None, pkgs=None): @@ -77,11 +70,11 @@ class Distro(distros.Distro): pkgs = [] # No user interaction possible, enable non-interactive mode - cmd = ['zypper', '--non-interactive'] + cmd = ["zypper", "--non-interactive"] # Command is the operation, such as install - if command == 'upgrade': - command = 'update' + if command == "upgrade": + command = "update" cmd.append(command) # args are the arguments to the command, not global options @@ -90,7 +83,7 @@ class Distro(distros.Distro): elif args and isinstance(args, list): cmd.extend(args) - pkglist = util.expand_package_list('%s-%s', pkgs) + pkglist = util.expand_package_list("%s-%s", pkgs) cmd.extend(pkglist) # Allow the output of this to flow outwards (ie not be captured) @@ -106,21 +99,25 @@ class Distro(distros.Distro): else: # Adjust the sysconfig clock zone setting clock_cfg = { - 'TIMEZONE': str(tz), + "TIMEZONE": str(tz), } rhutil.update_sysconfig_file(self.clock_conf_fn, clock_cfg) # This ensures that the correct tz will be used for the system util.copy(tz_file, self.tz_local_fn) def update_package_sources(self): - self._runner.run("update-sources", self.package_command, - ['refresh'], freq=PER_INSTANCE) + self._runner.run( + "update-sources", + self.package_command, + ["refresh"], + freq=PER_INSTANCE, + ) def _read_hostname(self, filename, default=None): - if self.uses_systemd() and filename.endswith('/previous-hostname'): + if self.uses_systemd() and filename.endswith("/previous-hostname"): return util.load_file(filename).strip() elif self.uses_systemd(): - (out, _err) = subp.subp(['hostname']) + (out, _err) = subp.subp(["hostname"]) if len(out): return out else: @@ -151,10 +148,10 @@ class Distro(distros.Distro): return (host_fn, self._read_hostname(host_fn)) def _write_hostname(self, hostname, filename): - if self.uses_systemd() and filename.endswith('/previous-hostname'): + if self.uses_systemd() and filename.endswith("/previous-hostname"): util.write_file(filename, hostname) elif self.uses_systemd(): - subp.subp(['hostnamectl', 'set-hostname', str(hostname)]) + subp.subp(["hostnamectl", "set-hostname", str(hostname)]) else: conf = None try: @@ -164,7 +161,7 @@ class Distro(distros.Distro): except IOError: pass if not conf: - conf = HostnameConf('') + conf = HostnameConf("") conf.set_hostname(hostname) util.write_file(filename, str(conf), 0o644) @@ -174,22 +171,28 @@ class Distro(distros.Distro): # Allow distro to determine the preferred ntp client list if not self._preferred_ntp_clients: - distro_info = util.system_info()['dist'] + distro_info = util.system_info()["dist"] name = distro_info[0] - major_ver = int(distro_info[1].split('.')[0]) + major_ver = int(distro_info[1].split(".")[0]) # This is horribly complicated because of a case of # "we do not care if versions should be increasing syndrome" - if ( - (major_ver >= 15 and 'openSUSE' not in name) or - (major_ver >= 15 and 'openSUSE' in name and major_ver != 42) + if (major_ver >= 15 and "openSUSE" not in name) or ( + major_ver >= 15 and "openSUSE" in name and major_ver != 42 ): - self._preferred_ntp_clients = ['chrony', - 'systemd-timesyncd', 'ntp'] + self._preferred_ntp_clients = [ + "chrony", + "systemd-timesyncd", + "ntp", + ] else: - self._preferred_ntp_clients = ['ntp', - 'systemd-timesyncd', 'chrony'] + self._preferred_ntp_clients = [ + "ntp", + "systemd-timesyncd", + "chrony", + ] return self._preferred_ntp_clients + # vi: ts=4 expandtab diff --git a/cloudinit/distros/parsers/__init__.py b/cloudinit/distros/parsers/__init__.py index 6b5b6dde..5bea2ae1 100644 --- a/cloudinit/distros/parsers/__init__.py +++ b/cloudinit/distros/parsers/__init__.py @@ -9,10 +9,11 @@ def chop_comment(text, comment_chars): comment_locations = [text.find(c) for c in comment_chars] comment_locations = [c for c in comment_locations if c != -1] if not comment_locations: - return (text, '') + return (text, "") min_comment = min(comment_locations) before_comment = text[0:min_comment] comment = text[min_comment:] return (before_comment, comment) + # vi: ts=4 expandtab diff --git a/cloudinit/distros/parsers/hostname.py b/cloudinit/distros/parsers/hostname.py index e74c083c..61674082 100644 --- a/cloudinit/distros/parsers/hostname.py +++ b/cloudinit/distros/parsers/hostname.py @@ -23,11 +23,11 @@ class HostnameConf(object): self.parse() contents = StringIO() for (line_type, components) in self._contents: - if line_type == 'blank': + if line_type == "blank": contents.write("%s\n" % (components[0])) - elif line_type == 'all_comment': + elif line_type == "all_comment": contents.write("%s\n" % (components[0])) - elif line_type == 'hostname': + elif line_type == "hostname": (hostname, tail) = components contents.write("%s%s\n" % (hostname, tail)) # Ensure trailing newline @@ -40,7 +40,7 @@ class HostnameConf(object): def hostname(self): self.parse() for (line_type, components) in self._contents: - if line_type == 'hostname': + if line_type == "hostname": return components[0] return None @@ -51,28 +51,28 @@ class HostnameConf(object): self.parse() replaced = False for (line_type, components) in self._contents: - if line_type == 'hostname': + if line_type == "hostname": components[0] = str(your_hostname) replaced = True if not replaced: - self._contents.append(('hostname', [str(your_hostname), ''])) + self._contents.append(("hostname", [str(your_hostname), ""])) def _parse(self, contents): entries = [] hostnames_found = set() for line in contents.splitlines(): if not len(line.strip()): - entries.append(('blank', [line])) + entries.append(("blank", [line])) continue - (head, tail) = chop_comment(line.strip(), '#') + (head, tail) = chop_comment(line.strip(), "#") if not len(head): - entries.append(('all_comment', [line])) + entries.append(("all_comment", [line])) continue - entries.append(('hostname', [head, tail])) + entries.append(("hostname", [head, tail])) hostnames_found.add(head) if len(hostnames_found) > 1: - raise IOError("Multiple hostnames (%s) found!" - % (hostnames_found)) + raise IOError("Multiple hostnames (%s) found!" % (hostnames_found)) return entries + # vi: ts=4 expandtab diff --git a/cloudinit/distros/parsers/hosts.py b/cloudinit/distros/parsers/hosts.py index 54e4e934..e43880af 100644 --- a/cloudinit/distros/parsers/hosts.py +++ b/cloudinit/distros/parsers/hosts.py @@ -25,7 +25,7 @@ class HostsConf(object): self.parse() options = [] for (line_type, components) in self._contents: - if line_type == 'option': + if line_type == "option": (pieces, _tail) = components if len(pieces) and pieces[0] == ip: options.append(pieces[1:]) @@ -35,7 +35,7 @@ class HostsConf(object): self.parse() n_entries = [] for (line_type, components) in self._contents: - if line_type != 'option': + if line_type != "option": n_entries.append((line_type, components)) continue else: @@ -48,35 +48,37 @@ class HostsConf(object): def add_entry(self, ip, canonical_hostname, *aliases): self.parse() - self._contents.append(('option', - ([ip, canonical_hostname] + list(aliases), ''))) + self._contents.append( + ("option", ([ip, canonical_hostname] + list(aliases), "")) + ) def _parse(self, contents): entries = [] for line in contents.splitlines(): if not len(line.strip()): - entries.append(('blank', [line])) + entries.append(("blank", [line])) continue - (head, tail) = chop_comment(line.strip(), '#') + (head, tail) = chop_comment(line.strip(), "#") if not len(head): - entries.append(('all_comment', [line])) + entries.append(("all_comment", [line])) continue - entries.append(('option', [head.split(None), tail])) + entries.append(("option", [head.split(None), tail])) return entries def __str__(self): self.parse() contents = StringIO() for (line_type, components) in self._contents: - if line_type == 'blank': + if line_type == "blank": contents.write("%s\n" % (components[0])) - elif line_type == 'all_comment': + elif line_type == "all_comment": contents.write("%s\n" % (components[0])) - elif line_type == 'option': + elif line_type == "option": (pieces, tail) = components pieces = [str(p) for p in pieces] pieces = "\t".join(pieces) contents.write("%s%s\n" % (pieces, tail)) return contents.getvalue() + # vi: ts=4 expandtab diff --git a/cloudinit/distros/parsers/networkmanager_conf.py b/cloudinit/distros/parsers/networkmanager_conf.py index ac51f122..4b669b0f 100644 --- a/cloudinit/distros/parsers/networkmanager_conf.py +++ b/cloudinit/distros/parsers/networkmanager_conf.py @@ -13,9 +13,9 @@ import configobj class NetworkManagerConf(configobj.ConfigObj): def __init__(self, contents): - configobj.ConfigObj.__init__(self, contents, - interpolation=False, - write_empty_values=False) + configobj.ConfigObj.__init__( + self, contents, interpolation=False, write_empty_values=False + ) def set_section_keypair(self, section_name, key, value): if section_name not in self.sections: diff --git a/cloudinit/distros/parsers/resolv_conf.py b/cloudinit/distros/parsers/resolv_conf.py index 62929d03..0ef4e147 100644 --- a/cloudinit/distros/parsers/resolv_conf.py +++ b/cloudinit/distros/parsers/resolv_conf.py @@ -6,9 +6,9 @@ from io import StringIO -from cloudinit.distros.parsers import chop_comment from cloudinit import log as logging from cloudinit import util +from cloudinit.distros.parsers import chop_comment LOG = logging.getLogger(__name__) @@ -26,12 +26,12 @@ class ResolvConf(object): @property def nameservers(self): self.parse() - return self._retr_option('nameserver') + return self._retr_option("nameserver") @property def local_domain(self): self.parse() - dm = self._retr_option('domain') + dm = self._retr_option("domain") if dm: return dm[0] return None @@ -39,7 +39,7 @@ class ResolvConf(object): @property def search_domains(self): self.parse() - current_sds = self._retr_option('search') + current_sds = self._retr_option("search") flat_sds = [] for sdlist in current_sds: for sd in sdlist.split(None): @@ -51,11 +51,11 @@ class ResolvConf(object): self.parse() contents = StringIO() for (line_type, components) in self._contents: - if line_type == 'blank': + if line_type == "blank": contents.write("\n") - elif line_type == 'all_comment': + elif line_type == "all_comment": contents.write("%s\n" % (components[0])) - elif line_type == 'option': + elif line_type == "option": (cfg_opt, cfg_value, comment_tail) = components line = "%s %s" % (cfg_opt, cfg_value) if len(comment_tail): @@ -66,7 +66,7 @@ class ResolvConf(object): def _retr_option(self, opt_name): found = [] for (line_type, components) in self._contents: - if line_type == 'option': + if line_type == "option": (cfg_opt, cfg_value, _comment_tail) = components if cfg_opt == opt_name: found.append(cfg_value) @@ -74,27 +74,29 @@ class ResolvConf(object): def add_nameserver(self, ns): self.parse() - current_ns = self._retr_option('nameserver') + current_ns = self._retr_option("nameserver") new_ns = list(current_ns) new_ns.append(str(ns)) new_ns = util.uniq_list(new_ns) if len(new_ns) == len(current_ns): return current_ns if len(current_ns) >= 3: - LOG.warning("ignoring nameserver %r: adding would " - "exceed the maximum of " - "'3' name servers (see resolv.conf(5))", ns) + LOG.warning( + "ignoring nameserver %r: adding would " + "exceed the maximum of " + "'3' name servers (see resolv.conf(5))", + ns, + ) return current_ns[:3] - self._remove_option('nameserver') + self._remove_option("nameserver") for n in new_ns: - self._contents.append(('option', ['nameserver', n, ''])) + self._contents.append(("option", ["nameserver", n, ""])) return new_ns def _remove_option(self, opt_name): - def remove_opt(item): line_type, components = item - if line_type != 'option': + if line_type != "option": return False (cfg_opt, _cfg_value, _comment_tail) = components if cfg_opt != opt_name: @@ -116,23 +118,26 @@ class ResolvConf(object): return new_sds if len(flat_sds) >= 6: # Hard restriction on only 6 search domains - raise ValueError(("Adding %r would go beyond the " - "'6' maximum search domains") % (search_domain)) + raise ValueError( + "Adding %r would go beyond the '6' maximum search domains" + % (search_domain) + ) s_list = " ".join(new_sds) if len(s_list) > 256: # Some hard limit on 256 chars total - raise ValueError(("Adding %r would go beyond the " - "256 maximum search list character limit") - % (search_domain)) - self._remove_option('search') - self._contents.append(('option', ['search', s_list, ''])) + raise ValueError( + "Adding %r would go beyond the " + "256 maximum search list character limit" % (search_domain) + ) + self._remove_option("search") + self._contents.append(("option", ["search", s_list, ""])) return flat_sds @local_domain.setter def local_domain(self, domain): self.parse() - self._remove_option('domain') - self._contents.append(('option', ['domain', str(domain), ''])) + self._remove_option("domain") + self._contents.append(("option", ["domain", str(domain), ""])) return domain def _parse(self, contents): @@ -140,24 +145,30 @@ class ResolvConf(object): for (i, line) in enumerate(contents.splitlines()): sline = line.strip() if not sline: - entries.append(('blank', [line])) + entries.append(("blank", [line])) continue - (head, tail) = chop_comment(line, ';#') + (head, tail) = chop_comment(line, ";#") if not len(head.strip()): - entries.append(('all_comment', [line])) + entries.append(("all_comment", [line])) continue if not tail: - tail = '' + tail = "" try: (cfg_opt, cfg_values) = head.split(None, 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']: + if cfg_opt not in [ + "nameserver", + "domain", + "search", + "sortlist", + "options", + ]: raise IOError("Unexpected resolv.conf option %s" % (cfg_opt)) entries.append(("option", [cfg_opt, cfg_values, tail])) return entries + # vi: ts=4 expandtab diff --git a/cloudinit/distros/parsers/sys_conf.py b/cloudinit/distros/parsers/sys_conf.py index dee4c551..4132734c 100644 --- a/cloudinit/distros/parsers/sys_conf.py +++ b/cloudinit/distros/parsers/sys_conf.py @@ -20,7 +20,7 @@ import configobj # See: http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html # or look at the 'param_expand()' function in the subst.c file in the bash # source tarball... -SHELL_VAR_RULE = r'[a-zA-Z_]+[a-zA-Z0-9_]*' +SHELL_VAR_RULE = r"[a-zA-Z_]+[a-zA-Z0-9_]*" SHELL_VAR_REGEXES = [ # Basic variables re.compile(r"\$" + SHELL_VAR_RULE), @@ -48,10 +48,11 @@ class SysConf(configobj.ConfigObj): ``configobj.ConfigObj.__init__`` (i.e. "a filename, file like object, or list of lines"). """ + def __init__(self, contents): - configobj.ConfigObj.__init__(self, contents, - interpolation=False, - write_empty_values=True) + configobj.ConfigObj.__init__( + self, contents, interpolation=False, write_empty_values=True + ) def __str__(self): contents = self.write() @@ -66,11 +67,13 @@ class SysConf(configobj.ConfigObj): if not isinstance(value, str): raise ValueError('Value "%s" is not a string' % (value)) if len(value) == 0: - return '' + return "" quot_func = None if value[0] in ['"', "'"] and value[-1] in ['"', "'"]: if len(value) == 1: - quot_func = (lambda x: self._get_single_quote(x) % x) + quot_func = ( + lambda x: self._get_single_quote(x) % x + ) # noqa: E731 else: # Quote whitespace if it isn't the start + end of a shell command if value.strip().startswith("$(") and value.strip().endswith(")"): @@ -82,11 +85,13 @@ class SysConf(configobj.ConfigObj): # leave it alone since the pipes.quote function likes # to use single quotes which won't get expanded... if re.search(r"[\n\"']", value): - quot_func = (lambda x: - self._get_triple_quote(x) % x) + quot_func = ( + lambda x: self._get_triple_quote(x) % x + ) # noqa: E731 else: - quot_func = (lambda x: - self._get_single_quote(x) % x) + quot_func = ( + lambda x: self._get_single_quote(x) % x + ) # noqa: E731 else: quot_func = pipes.quote if not quot_func: @@ -99,10 +104,13 @@ class SysConf(configobj.ConfigObj): val = self._decode_element(self._quote(this_entry)) key = self._decode_element(self._quote(entry)) cmnt = self._decode_element(comment) - return '%s%s%s%s%s' % (indent_string, - key, - self._a_to_u('='), - val, - cmnt) + return "%s%s%s%s%s" % ( + indent_string, + key, + self._a_to_u("="), + val, + cmnt, + ) + # vi: ts=4 expandtab diff --git a/cloudinit/distros/photon.py b/cloudinit/distros/photon.py index 4ff90ea6..14cefe90 100644 --- a/cloudinit/distros/photon.py +++ b/cloudinit/distros/photon.py @@ -5,28 +5,25 @@ # # This file is part of cloud-init. See LICENSE file for license information. -from cloudinit import net -from cloudinit import util -from cloudinit import subp -from cloudinit import distros -from cloudinit import helpers +from cloudinit import distros, helpers from cloudinit import log as logging -from cloudinit.settings import PER_INSTANCE +from cloudinit import net, subp, util from cloudinit.distros import rhel_util as rhutil +from cloudinit.settings import PER_INSTANCE LOG = logging.getLogger(__name__) class Distro(distros.Distro): - systemd_hostname_conf_fn = '/etc/hostname' - network_conf_dir = '/etc/systemd/network/' - systemd_locale_conf_fn = '/etc/locale.conf' - resolve_conf_fn = '/etc/systemd/resolved.conf' + systemd_hostname_conf_fn = "/etc/hostname" + network_conf_dir = "/etc/systemd/network/" + systemd_locale_conf_fn = "/etc/locale.conf" + resolve_conf_fn = "/etc/systemd/resolved.conf" renderer_configs = { - 'networkd': { - 'resolv_conf_fn': resolve_conf_fn, - 'network_conf_dir': network_conf_dir, + "networkd": { + "resolv_conf_fn": resolve_conf_fn, + "network_conf_dir": network_conf_dir, } } @@ -39,33 +36,34 @@ class Distro(distros.Distro): # calls from repeatly happening (when they # should only happen say once per instance...) self._runner = helpers.Runners(paths) - self.osfamily = 'photon' - self.init_cmd = ['systemctl'] + self.osfamily = "photon" + self.init_cmd = ["systemctl"] def exec_cmd(self, cmd, capture=True): - LOG.debug('Attempting to run: %s', cmd) + LOG.debug("Attempting to run: %s", cmd) try: (out, err) = subp.subp(cmd, capture=capture) if err: - LOG.warning('Running %s resulted in stderr output: %s', - cmd, err) + LOG.warning( + "Running %s resulted in stderr output: %s", cmd, err + ) return True, out, err return False, out, err except subp.ProcessExecutionError: - util.logexc(LOG, 'Command %s failed', cmd) + util.logexc(LOG, "Command %s failed", cmd) return True, None, None def generate_fallback_config(self): - key = 'disable_fallback_netcfg' + key = "disable_fallback_netcfg" disable_fallback_netcfg = self._cfg.get(key, True) - LOG.debug('%s value is: %s', key, disable_fallback_netcfg) + LOG.debug("%s value is: %s", key, disable_fallback_netcfg) if not disable_fallback_netcfg: return net.generate_fallback_config() LOG.info( - 'Skipping generate_fallback_config. Rely on PhotonOS default ' - 'network config' + "Skipping generate_fallback_config. Rely on PhotonOS default " + "network config" ) return None @@ -76,7 +74,7 @@ class Distro(distros.Distro): out_fn = self.systemd_locale_conf_fn locale_cfg = { - 'LANG': locale, + "LANG": locale, } rhutil.update_sysconfig_file(out_fn, locale_cfg) @@ -84,36 +82,42 @@ class Distro(distros.Distro): # rhutil will modify /etc/locale.conf # For locale change to take effect, reboot is needed or we can restart # systemd-localed. This is equivalent of localectl - cmd = ['systemctl', 'restart', 'systemd-localed'] + cmd = ["systemctl", "restart", "systemd-localed"] self.exec_cmd(cmd) def install_packages(self, pkglist): # self.update_package_sources() - self.package_command('install', pkgs=pkglist) + self.package_command("install", pkgs=pkglist) def _write_hostname(self, hostname, filename): - if filename and filename.endswith('/previous-hostname'): + if filename and filename.endswith("/previous-hostname"): util.write_file(filename, hostname) else: - ret, _out, err = self.exec_cmd(['hostnamectl', 'set-hostname', - str(hostname)]) + ret, _out, err = self.exec_cmd( + ["hostnamectl", "set-hostname", str(hostname)] + ) if ret: - LOG.warning(('Error while setting hostname: %s\n' - 'Given hostname: %s', err, hostname)) + LOG.warning( + ( + "Error while setting hostname: %s\nGiven hostname: %s", + err, + hostname, + ) + ) def _read_system_hostname(self): sys_hostname = self._read_hostname(self.systemd_hostname_conf_fn) return (self.systemd_hostname_conf_fn, sys_hostname) def _read_hostname(self, filename, default=None): - if filename and filename.endswith('/previous-hostname'): + if filename and filename.endswith("/previous-hostname"): return util.load_file(filename).strip() - _ret, out, _err = self.exec_cmd(['hostname', '-f']) + _ret, out, _err = self.exec_cmd(["hostname", "-f"]) return out.strip() if out else default def _get_localhost_ip(self): - return '127.0.1.1' + return "127.0.1.1" def set_timezone(self, tz): distros.set_etc_timezone(tz=tz, tz_file=self._find_tz_file(tz)) @@ -122,7 +126,7 @@ class Distro(distros.Distro): if not pkgs: pkgs = [] - cmd = ['tdnf', '-y'] + cmd = ["tdnf", "-y"] if args and isinstance(args, str): cmd.append(args) elif args and isinstance(args, list): @@ -130,13 +134,17 @@ class Distro(distros.Distro): cmd.append(command) - pkglist = util.expand_package_list('%s-%s', pkgs) + pkglist = util.expand_package_list("%s-%s", pkgs) cmd.extend(pkglist) ret, _out, err = self.exec_cmd(cmd) if ret: - LOG.error('Error while installing packages: %s', err) + LOG.error("Error while installing packages: %s", err) def update_package_sources(self): - self._runner.run('update-sources', self.package_command, - ['makecache'], freq=PER_INSTANCE) + self._runner.run( + "update-sources", + self.package_command, + ["makecache"], + freq=PER_INSTANCE, + ) diff --git a/cloudinit/distros/rhel.py b/cloudinit/distros/rhel.py index c9ee2747..84744ece 100644 --- a/cloudinit/distros/rhel.py +++ b/cloudinit/distros/rhel.py @@ -8,12 +8,9 @@ # # This file is part of cloud-init. See LICENSE file for license information. -from cloudinit import distros -from cloudinit import helpers +from cloudinit import distros, helpers from cloudinit import log as logging -from cloudinit import subp -from cloudinit import util - +from cloudinit import subp, util from cloudinit.distros import rhel_util from cloudinit.settings import PER_INSTANCE @@ -22,30 +19,30 @@ LOG = logging.getLogger(__name__) def _make_sysconfig_bool(val): if val: - return 'yes' + return "yes" else: - return 'no' + return "no" class Distro(distros.Distro): # See: https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Networking_Guide/sec-Network_Configuration_Using_sysconfig_Files.html # noqa clock_conf_fn = "/etc/sysconfig/clock" - locale_conf_fn = '/etc/sysconfig/i18n' - systemd_locale_conf_fn = '/etc/locale.conf' + locale_conf_fn = "/etc/sysconfig/i18n" + systemd_locale_conf_fn = "/etc/locale.conf" network_conf_fn = "/etc/sysconfig/network" hostname_conf_fn = "/etc/sysconfig/network" systemd_hostname_conf_fn = "/etc/hostname" - network_script_tpl = '/etc/sysconfig/network-scripts/ifcfg-%s' + network_script_tpl = "/etc/sysconfig/network-scripts/ifcfg-%s" tz_local_fn = "/etc/localtime" usr_lib_exec = "/usr/libexec" renderer_configs = { - 'sysconfig': { - 'control': 'etc/sysconfig/network', - 'iface_templates': '%(base)s/network-scripts/ifcfg-%(name)s', - 'route_templates': { - 'ipv4': '%(base)s/network-scripts/route-%(name)s', - 'ipv6': '%(base)s/network-scripts/route6-%(name)s' - } + "sysconfig": { + "control": "etc/sysconfig/network", + "iface_templates": "%(base)s/network-scripts/ifcfg-%(name)s", + "route_templates": { + "ipv4": "%(base)s/network-scripts/route-%(name)s", + "ipv6": "%(base)s/network-scripts/route6-%(name)s", + }, } } @@ -59,11 +56,11 @@ class Distro(distros.Distro): # calls from repeatly happening (when they # should only happen say once per instance...) self._runner = helpers.Runners(paths) - self.osfamily = 'redhat' - cfg['ssh_svcname'] = 'sshd' + self.osfamily = "redhat" + cfg["ssh_svcname"] = "sshd" def install_packages(self, pkglist): - self.package_command('install', pkgs=pkglist) + self.package_command("install", pkgs=pkglist) def apply_locale(self, locale, out_fn=None): if self.uses_systemd(): @@ -74,20 +71,20 @@ class Distro(distros.Distro): if not out_fn: out_fn = self.locale_conf_fn locale_cfg = { - 'LANG': locale, + "LANG": locale, } rhel_util.update_sysconfig_file(out_fn, locale_cfg) def _write_hostname(self, hostname, filename): # systemd will never update previous-hostname for us, so # we need to do it ourselves - if self.uses_systemd() and filename.endswith('/previous-hostname'): + if self.uses_systemd() and filename.endswith("/previous-hostname"): util.write_file(filename, hostname) elif self.uses_systemd(): - subp.subp(['hostnamectl', 'set-hostname', str(hostname)]) + subp.subp(["hostnamectl", "set-hostname", str(hostname)]) else: host_cfg = { - 'HOSTNAME': hostname, + "HOSTNAME": hostname, } rhel_util.update_sysconfig_file(filename, host_cfg) @@ -99,18 +96,18 @@ class Distro(distros.Distro): return (host_fn, self._read_hostname(host_fn)) def _read_hostname(self, filename, default=None): - if self.uses_systemd() and filename.endswith('/previous-hostname'): + if self.uses_systemd() and filename.endswith("/previous-hostname"): return util.load_file(filename).strip() elif self.uses_systemd(): - (out, _err) = subp.subp(['hostname']) + (out, _err) = subp.subp(["hostname"]) if len(out): return out else: return default else: (_exists, contents) = rhel_util.read_sysconfig_file(filename) - if 'HOSTNAME' in contents: - return contents['HOSTNAME'] + if "HOSTNAME" in contents: + return contents["HOSTNAME"] else: return default @@ -124,7 +121,7 @@ class Distro(distros.Distro): else: # Adjust the sysconfig clock zone setting clock_cfg = { - 'ZONE': str(tz), + "ZONE": str(tz), } rhel_util.update_sysconfig_file(self.clock_conf_fn, clock_cfg) # This ensures that the correct tz will be used for the system @@ -134,18 +131,18 @@ class Distro(distros.Distro): if pkgs is None: pkgs = [] - if subp.which('dnf'): - LOG.debug('Using DNF for package management') - cmd = ['dnf'] + if subp.which("dnf"): + LOG.debug("Using DNF for package management") + cmd = ["dnf"] else: - LOG.debug('Using YUM for package management') + LOG.debug("Using YUM for package management") # the '-t' argument makes yum tolerant of errors on the command # line with regard to packages. # # For example: if you request to install foo, bar and baz and baz # is installed; yum won't error out complaining that baz is already # installed. - cmd = ['yum', '-t'] + cmd = ["yum", "-t"] # Determines whether or not yum prompts for confirmation # of critical actions. We don't want to prompt... cmd.append("-y") @@ -157,14 +154,19 @@ class Distro(distros.Distro): cmd.append(command) - pkglist = util.expand_package_list('%s-%s', pkgs) + pkglist = util.expand_package_list("%s-%s", pkgs) cmd.extend(pkglist) # Allow the output of this to flow outwards (ie not be captured) subp.subp(cmd, capture=False) def update_package_sources(self): - self._runner.run("update-sources", self.package_command, - ["makecache"], freq=PER_INSTANCE) + self._runner.run( + "update-sources", + self.package_command, + ["makecache"], + freq=PER_INSTANCE, + ) + # vi: ts=4 expandtab diff --git a/cloudinit/distros/rhel_util.py b/cloudinit/distros/rhel_util.py index d71394b4..c96f93b5 100644 --- a/cloudinit/distros/rhel_util.py +++ b/cloudinit/distros/rhel_util.py @@ -8,10 +8,9 @@ # # This file is part of cloud-init. See LICENSE file for license information. -from cloudinit.distros.parsers.sys_conf import SysConf - from cloudinit import log as logging from cloudinit import util +from cloudinit.distros.parsers.sys_conf import SysConf LOG = logging.getLogger(__name__) @@ -49,4 +48,5 @@ def read_sysconfig_file(fn): contents = [] return (exists, SysConf(contents)) + # vi: ts=4 expandtab diff --git a/cloudinit/distros/rocky.py b/cloudinit/distros/rocky.py index edb3165d..3dc0a342 100644 --- a/cloudinit/distros/rocky.py +++ b/cloudinit/distros/rocky.py @@ -6,4 +6,5 @@ from cloudinit.distros import rhel class Distro(rhel.Distro): pass + # vi: ts=4 expandtab diff --git a/cloudinit/distros/sles.py b/cloudinit/distros/sles.py index f3bfb9c2..484214e7 100644 --- a/cloudinit/distros/sles.py +++ b/cloudinit/distros/sles.py @@ -10,4 +10,5 @@ from cloudinit.distros import opensuse class Distro(opensuse.Distro): pass + # vi: ts=4 expandtab diff --git a/cloudinit/distros/ubuntu.py b/cloudinit/distros/ubuntu.py index 2a1f93d9..ec6470a9 100644 --- a/cloudinit/distros/ubuntu.py +++ b/cloudinit/distros/ubuntu.py @@ -9,41 +9,44 @@ # # This file is part of cloud-init. See LICENSE file for license information. -from cloudinit.distros import debian -from cloudinit.distros import PREFERRED_NTP_CLIENTS -from cloudinit import util - import copy +from cloudinit import util +from cloudinit.distros import PREFERRED_NTP_CLIENTS, debian -class Distro(debian.Distro): +class Distro(debian.Distro): def __init__(self, name, cfg, paths): super(Distro, self).__init__(name, cfg, paths) # Ubuntu specific network cfg locations self.network_conf_fn = { "eni": "/etc/network/interfaces.d/50-cloud-init.cfg", - "netplan": "/etc/netplan/50-cloud-init.yaml" + "netplan": "/etc/netplan/50-cloud-init.yaml", } self.renderer_configs = { - "eni": {"eni_path": self.network_conf_fn["eni"], - "eni_header": debian.NETWORK_FILE_HEADER}, - "netplan": {"netplan_path": self.network_conf_fn["netplan"], - "netplan_header": debian.NETWORK_FILE_HEADER, - "postcmds": True} + "eni": { + "eni_path": self.network_conf_fn["eni"], + "eni_header": debian.NETWORK_FILE_HEADER, + }, + "netplan": { + "netplan_path": self.network_conf_fn["netplan"], + "netplan_header": debian.NETWORK_FILE_HEADER, + "postcmds": True, + }, } @property def preferred_ntp_clients(self): """The preferred ntp client is dependent on the version.""" if not self._preferred_ntp_clients: - (_name, _version, codename) = util.system_info()['dist'] + (_name, _version, codename) = util.system_info()["dist"] # Xenial cloud-init only installed ntp, UbuntuCore has timesyncd. if codename == "xenial" and not util.system_is_snappy(): - self._preferred_ntp_clients = ['ntp'] + self._preferred_ntp_clients = ["ntp"] else: - self._preferred_ntp_clients = ( - copy.deepcopy(PREFERRED_NTP_CLIENTS)) + self._preferred_ntp_clients = copy.deepcopy( + PREFERRED_NTP_CLIENTS + ) return self._preferred_ntp_clients diff --git a/cloudinit/distros/ug_util.py b/cloudinit/distros/ug_util.py index 600b743f..72766392 100755 --- a/cloudinit/distros/ug_util.py +++ b/cloudinit/distros/ug_util.py @@ -10,8 +10,7 @@ # This file is part of cloud-init. See LICENSE file for license information. from cloudinit import log as logging -from cloudinit import type_utils -from cloudinit import util +from cloudinit import type_utils, util LOG = logging.getLogger(__name__) @@ -23,7 +22,7 @@ LOG = logging.getLogger(__name__) # standard form used in the rest of cloud-init def _normalize_groups(grp_cfg): if isinstance(grp_cfg, str): - grp_cfg = grp_cfg.strip().split(',') + grp_cfg = grp_cfg.strip().split(",") if isinstance(grp_cfg, list): c_grp_cfg = {} @@ -31,8 +30,10 @@ def _normalize_groups(grp_cfg): if isinstance(i, dict): for k, v in i.items(): if not isinstance(v, (list, str)): - raise TypeError('Bad group member type %s' - % (type_utils.obj_name(v))) + raise TypeError( + "Bad group member type %s" + % (type_utils.obj_name(v)) + ) if isinstance(v, list): c_grp_cfg.setdefault(k, []).extend(v) @@ -42,8 +43,9 @@ def _normalize_groups(grp_cfg): if i not in c_grp_cfg: c_grp_cfg[i] = [] else: - raise TypeError('Unknown group name type %s' - % (type_utils.obj_name(i))) + raise TypeError( + "Unknown group name type %s" % (type_utils.obj_name(i)) + ) grp_cfg = c_grp_cfg groups = {} @@ -51,8 +53,10 @@ def _normalize_groups(grp_cfg): for grp_name, grp_members in grp_cfg.items(): groups[grp_name] = util.uniq_merge_sorted(grp_members) else: - raise TypeError(('Group config must be list, dict or string type only ' - 'but found %s') % (type_utils.obj_name(grp_cfg))) + raise TypeError( + "Group config must be list, dict or string type only but found %s" + % (type_utils.obj_name(grp_cfg)) + ) return groups @@ -73,11 +77,13 @@ def _normalize_users(u_cfg, def_user_cfg=None): if util.is_true(v): ad_ucfg.append(str(k)) elif isinstance(v, dict): - v['name'] = k + v["name"] = k ad_ucfg.append(v) else: - raise TypeError(('Unmappable user value type %s for key %s') - % (type_utils.obj_name(v), k)) + raise TypeError( + "Unmappable user value type %s for key %s" + % (type_utils.obj_name(v), k) + ) u_cfg = ad_ucfg elif isinstance(u_cfg, str): u_cfg = util.uniq_merge_sorted(u_cfg) @@ -89,13 +95,14 @@ def _normalize_users(u_cfg, def_user_cfg=None): if u and u not in users: users[u] = {} elif isinstance(user_config, dict): - n = user_config.pop('name', 'default') + n = user_config.pop("name", "default") prev_config = users.get(n) or {} users[n] = util.mergemanydict([prev_config, user_config]) else: - raise TypeError(('User config must be dictionary/list or string ' - ' types only and not %s') - % (type_utils.obj_name(user_config))) + raise TypeError( + "User config must be dictionary/list or string " + " types only and not %s" % (type_utils.obj_name(user_config)) + ) # Ensure user options are in the right python friendly format if users: @@ -103,7 +110,7 @@ def _normalize_users(u_cfg, def_user_cfg=None): for uname, uconfig in users.items(): c_uconfig = {} for k, v in uconfig.items(): - k = k.replace('-', '_').strip() + k = k.replace("-", "_").strip() if k: c_uconfig[k] = v c_users[uname] = c_uconfig @@ -111,33 +118,34 @@ def _normalize_users(u_cfg, def_user_cfg=None): # Fix the default user into the actual default user name and replace it. def_user = None - if users and 'default' in users: - def_config = users.pop('default') + if users and "default" in users: + def_config = users.pop("default") if def_user_cfg: # Pickup what the default 'real name' is and any groups that are # provided by the default config def_user_cfg = def_user_cfg.copy() - def_user = def_user_cfg.pop('name') - def_groups = def_user_cfg.pop('groups', []) + def_user = def_user_cfg.pop("name") + def_groups = def_user_cfg.pop("groups", []) # Pick any config + groups for the user name that we may have # extracted previously parsed_config = users.pop(def_user, {}) - parsed_groups = parsed_config.get('groups', []) + parsed_groups = parsed_config.get("groups", []) # Now merge the extracted groups with the default config provided users_groups = util.uniq_merge_sorted(parsed_groups, def_groups) - parsed_config['groups'] = ','.join(users_groups) + parsed_config["groups"] = ",".join(users_groups) # The real config for the default user is the combination of the # default user config provided by the distro, the default user # config provided by the above merging for the user 'default' and # then the parsed config from the user's 'real name' which does not # have to be 'default' (but could be) - users[def_user] = util.mergemanydict([def_user_cfg, def_config, - parsed_config]) + users[def_user] = util.mergemanydict( + [def_user_cfg, def_config, parsed_config] + ) # Ensure that only the default user that we found (if any) is actually # marked as the default user for uname, uconfig in users.items(): - uconfig['default'] = (uname == def_user if def_user else False) + uconfig["default"] = uname == def_user if def_user else False return users @@ -161,14 +169,17 @@ def normalize_users_groups(cfg, distro): # overrides the concept of the default user if provided in the user: XYZ # format. old_user = {} - if 'user' in cfg and cfg['user']: - old_user = cfg['user'] + if "user" in cfg and cfg["user"]: + old_user = cfg["user"] # Translate it into a format that will be more useful going forward if isinstance(old_user, str): - old_user = {'name': old_user} + old_user = {"name": old_user} elif not isinstance(old_user, dict): - LOG.warning(("Format for 'user' key must be a string or dictionary" - " and not %s"), type_utils.obj_name(old_user)) + LOG.warning( + "Format for 'user' key must be a string or dictionary" + " and not %s", + type_utils.obj_name(old_user), + ) old_user = {} # If no old user format, then assume the distro provides what the 'default' @@ -179,33 +190,37 @@ def normalize_users_groups(cfg, distro): try: distro_user_config = distro.get_default_user() except NotImplementedError: - LOG.warning(('Distro has not implemented default user access. No ' - 'distribution provided default user will be normalized.')) + LOG.warning( + "Distro has not implemented default user access. No " + "distribution provided default user will be normalized." + ) # Merge the old user (which may just be an empty dict when not present) # with the distro provided default user configuration so that the old user # style picks up all the distribution specific attributes (if any) default_user_config = util.mergemanydict([old_user, distro_user_config]) - base_users = cfg.get('users', []) + base_users = cfg.get("users", []) if not isinstance(base_users, (list, dict, str)): - LOG.warning(("Format for 'users' key must be a comma separated string" - " or a dictionary or a list but found %s"), - type_utils.obj_name(base_users)) + LOG.warning( + "Format for 'users' key must be a comma separated string" + " or a dictionary or a list but found %s", + type_utils.obj_name(base_users), + ) base_users = [] if old_user: # When 'user:' is provided, it should be made as the default user if isinstance(base_users, list): - base_users.append({'name': 'default'}) + base_users.append({"name": "default"}) elif isinstance(base_users, dict): - base_users['default'] = dict(base_users).get('default', True) + base_users["default"] = dict(base_users).get("default", True) elif isinstance(base_users, str): - base_users += ',default' + base_users += ",default" groups = {} - if 'groups' in cfg: - groups = _normalize_groups(cfg['groups']) + if "groups" in cfg: + groups = _normalize_groups(cfg["groups"]) users = _normalize_users(base_users, default_user_config) return (users, groups) @@ -219,9 +234,9 @@ def extract_default(users, default_name=None, default_config=None): def safe_find(entry): config = entry[1] - if not config or 'default' not in config: + if not config or "default" not in config: return False - return config['default'] + return config["default"] tmp_users = dict(filter(safe_find, users.items())) if not tmp_users: @@ -229,7 +244,8 @@ def extract_default(users, default_name=None, default_config=None): name = list(tmp_users)[0] config = tmp_users[name] - config.pop('default', None) + config.pop("default", None) return (name, config) + # vi: ts=4 expandtab diff --git a/cloudinit/distros/virtuozzo.py b/cloudinit/distros/virtuozzo.py index edb3165d..3dc0a342 100644 --- a/cloudinit/distros/virtuozzo.py +++ b/cloudinit/distros/virtuozzo.py @@ -6,4 +6,5 @@ from cloudinit.distros import rhel class Distro(rhel.Distro): pass + # vi: ts=4 expandtab |