File: arch.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 (150 lines) | stat: -rw-r--r-- 5,037 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
150
# Copyright (C) 2014 Rackspace, US Inc.
#
# Author: Nate House <nathan.house@rackspace.com>
#
# 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.net.netplan import CLOUDINIT_NETPLAN_FILE
from cloudinit.settings import PER_ALWAYS, PER_INSTANCE

LOG = logging.getLogger(__name__)


class Distro(distros.Distro):
    locale_gen_fn = "/etc/locale.gen"
    init_cmd = ["systemctl"]  # init scripts
    renderer_configs = {
        "netplan": {
            "netplan_path": CLOUDINIT_NETPLAN_FILE,
            "netplan_header": "# generated by cloud-init\n",
            "postcmds": True,
        }
    }

    def __init__(self, name, cfg, paths):
        distros.Distro.__init__(self, name, cfg, paths)
        # 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 = "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,
            )
        lines = [
            util.make_header(),
            # Hard-coding the charset isn't ideal, but there is no other way.
            "%s UTF-8" % (locale),
            "",
        ]
        util.write_file(self.locale_gen_fn, "\n".join(lines))
        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)

    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("")
        conf.set_hostname(hostname)
        util.write_file(filename, str(conf), omode="w", mode=0o644)

    def _read_system_hostname(self):
        sys_hostname = self._read_hostname(self.hostname_conf_fn)
        return (self.hostname_conf_fn, sys_hostname)

    def _read_hostname_conf(self, 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

    # 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
        )
        try:
            subp.subp(["hostnamectl", "--transient", "set-hostname", hostname])
        except subp.ProcessExecutionError:
            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))

    def package_command(self, command, args=None, pkgs=None):
        if pkgs is None:
            pkgs = []

        cmd = ["pacman", "-Sy", "--quiet", "--noconfirm"]
        # Redirect output

        if args and isinstance(args, str):
            cmd.append(args)
        elif args and isinstance(args, list):
            cmd.extend(args)

        if command == "upgrade":
            command = "-u"
        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,
            ["-y"],
            freq=PER_ALWAYS if force else PER_INSTANCE,
        )