File: gentoo.py

package info (click to toggle)
cloud-init 25.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 12,412 kB
  • sloc: python: 135,894; sh: 3,883; makefile: 141; javascript: 30; xml: 22
file content (149 lines) | stat: -rw-r--r-- 4,990 bytes parent folder | download | duplicates (3)
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,
        )