1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
# Copyright (C) 2014 Rackspace, US Inc.
# Copyright (C) 2016 Matthew Thode.
# Copyright (C) 2024 Andreas K. Huettel
#
# Author: Nate House <nathan.house@rackspace.com>
# Author: Matthew Thode <prometheanfire@gentoo.org>
# Author: Andreas K. Huettel <dilfridge@gentoo.org>
#
# This file is part of cloud-init. See LICENSE file for license information.
import logging
from cloudinit import distros, helpers, subp, util
from cloudinit.distros import PackageList
from cloudinit.distros.parsers.hostname import HostnameConf
from cloudinit.settings import PER_ALWAYS, PER_INSTANCE
LOG = logging.getLogger(__name__)
class Distro(distros.Distro):
locale_gen_fn = "/etc/locale.gen"
default_locale = "en_US.UTF-8"
# C.UTF8 makes sense to generate, but is not selected
# Add /etc/locale.gen entries to this list to support more locales
locales = ["C.UTF8 UTF-8", "en_US.UTF-8 UTF-8"]
def __init__(self, name, cfg, paths):
distros.Distro.__init__(self, name, cfg, paths)
if distros.uses_systemd():
self.hostname_conf_fn = "/etc/hostname"
else:
self.hostname_conf_fn = "/etc/conf.d/hostname"
# This will be used to restrict certain
# calls from repeatedly happening (when they
# should only happen say once per instance...)
self._runner = helpers.Runners(paths)
self.osfamily = "gentoo"
def apply_locale(self, _, out_fn=None):
"""Locales need to be added to /etc/locale.gen and generated prior
to selection. Default to en_US.UTF-8 for simplicity.
"""
util.write_file(self.locale_gen_fn, "\n".join(self.locales), mode=644)
# generate locales
subp.subp(["locale-gen"], capture=False)
# select locale, works for both openrc and systemd
subp.subp(
["eselect", "locale", "set", self.default_locale], capture=False
)
def install_packages(self, pkglist: PackageList):
self.update_package_sources()
self.package_command("", pkgs=pkglist)
def _write_hostname(self, hostname, filename):
conf = None
try:
# Try to update the previous one
# so lets see if we can read it first.
conf = self._read_hostname_conf(filename)
except IOError:
create_hostname_file = util.get_cfg_option_bool(
self._cfg, "create_hostname_file", True
)
if create_hostname_file:
pass
else:
LOG.info(
"create_hostname_file is False; hostname file not created"
)
return
if not conf:
conf = HostnameConf("")
if distros.uses_systemd():
# Gentoo uses the same format for /etc/hostname as everyone else-
# only the hostname by itself. Works for openrc and systemd, but
# openrc has its own config file and /etc/hostname is generated.
conf.set_hostname(hostname)
else:
# Openrc generates /etc/hostname from /etc/conf.d/hostname with the
# differing format
# hostname="the-actual-hostname"
conf.set_hostname('hostname="%s"' % hostname)
util.write_file(filename, str(conf), 0o644)
def _read_system_hostname(self):
sys_hostname = self._read_hostname(self.hostname_conf_fn)
return self.hostname_conf_fn, sys_hostname
@staticmethod
def _read_hostname_conf(filename):
conf = HostnameConf(util.load_text_file(filename))
conf.parse()
return conf
def _read_hostname(self, filename, default=None):
hostname = None
try:
conf = self._read_hostname_conf(filename)
hostname = conf.hostname
except IOError:
pass
if not hostname:
return default
return hostname
def set_timezone(self, tz):
distros.set_etc_timezone(tz=tz, tz_file=self._find_tz_file(tz))
def package_command(self, command, args=None, pkgs=None):
cmd = ["emerge"]
# Redirect output
cmd.append("--quiet")
if command == "upgrade":
cmd.extend(["--update", "world"])
else:
if pkgs is None:
pkgs = []
if args and isinstance(args, str):
cmd.append(args)
elif args and isinstance(args, list):
cmd.extend(args)
if command:
cmd.append(command)
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, *, force=False):
self._runner.run(
"update-sources",
self.package_command,
["--sync"],
freq=PER_ALWAYS if force else PER_INSTANCE,
)
|