From 3664338949590765ed60fc39531c5039582b5b0c Mon Sep 17 00:00:00 2001 From: leavelet Date: Tue, 21 May 2024 22:35:09 +0800 Subject: [PATCH 1/5] feat: Add AOSC OS support --- cloudinit/config/cc_ca_certs.py | 10 ++- cloudinit/config/cc_ntp.py | 7 ++ cloudinit/distros/__init__.py | 1 + cloudinit/distros/aosc.py | 116 +++++++++++++++++++++++++++ cloudinit/util.py | 1 + config/cloud.cfg.tmpl | 10 +-- tests/unittests/distros/test_aosc.py | 14 ++++ tools/.github-cla-signers | 1 + tools/render-template | 1 + 9 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 cloudinit/distros/aosc.py create mode 100644 tests/unittests/distros/test_aosc.py diff --git a/cloudinit/config/cc_ca_certs.py b/cloudinit/config/cc_ca_certs.py index 3dea5689ad6..4dd9dd131f8 100644 --- a/cloudinit/config/cc_ca_certs.py +++ b/cloudinit/config/cc_ca_certs.py @@ -24,6 +24,13 @@ "ca_cert_update_cmd": ["update-ca-certificates"], } DISTRO_OVERRIDES = { + "aosc": { + "ca_cert_path": "/etc/ssl/certs/", + "ca_cert_local_path": "/etc/ssl/certs/", + "ca_cert_filename": "cloud-init-ca-cert-{cert_index}.pem", + "ca_cert_config": "/etc/ca-certificates/conf.d/cloud-init.conf", + "ca_cert_update_cmd": ["update-ca-bundle"], + }, "fedora": { "ca_cert_path": "/etc/pki/ca-trust/", "ca_cert_local_path": "/usr/share/pki/ca-trust-source/", @@ -86,6 +93,7 @@ """ distros = [ "almalinux", + "aosc", "cloudlinux", "alpine", "debian", @@ -183,7 +191,7 @@ def disable_default_ca_certs(distro_name, distro_cfg): """ if distro_name in ["rhel", "photon"]: remove_default_ca_certs(distro_cfg) - elif distro_name in ["alpine", "debian", "ubuntu"]: + elif distro_name in ["alpine", "aosc", "debian", "ubuntu"]: disable_system_ca_certs(distro_cfg) if distro_name in ["debian", "ubuntu"]: diff --git a/cloudinit/config/cc_ntp.py b/cloudinit/config/cc_ntp.py index 0de9c6f7bef..c8bc8b15d20 100644 --- a/cloudinit/config/cc_ntp.py +++ b/cloudinit/config/cc_ntp.py @@ -25,6 +25,7 @@ distros = [ "almalinux", "alpine", + "aosc", "azurelinux", "centos", "cloudlinux", @@ -110,6 +111,12 @@ "service_name": "ntpd", }, }, + "aosc": { + "systemd-timesyncd": { + "check_exe": "/usr/lib/systemd/systemd-timesyncd", + "confpath": "/etc/systemd/timesyncd.conf", + }, + }, "azurelinux": { "chrony": { "service_name": "chronyd", diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py index 90227675ec7..7b946efe599 100644 --- a/cloudinit/distros/__init__.py +++ b/cloudinit/distros/__init__.py @@ -59,6 +59,7 @@ OSFAMILIES = { "alpine": ["alpine"], + "aosc": ["aosc"], "arch": ["arch"], "debian": ["debian", "ubuntu"], "freebsd": ["freebsd", "dragonfly"], diff --git a/cloudinit/distros/aosc.py b/cloudinit/distros/aosc.py new file mode 100644 index 00000000000..69f83d3f399 --- /dev/null +++ b/cloudinit/distros/aosc.py @@ -0,0 +1,116 @@ +# Copyright (C) 2024 AOSC Developers +# +# Author: Yuanhang Sun +# +# 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, rhel_util +from cloudinit.distros.parsers.hostname import HostnameConf +from cloudinit.settings import PER_INSTANCE + +LOG = logging.getLogger(__name__) + + +class Distro(distros.Distro): + systemd_locale_conf_fn = "/etc/locale.conf" + init_cmd = ["systemctl"] + network_conf_dir = "/etc/systemd/network/" + resolve_conf_fn = "/etc/systemd/resolved.conf" + tz_local_fn = "/etc/localtime" + + renderer_configs = { + "networkd": { + "resolv_conf_fn": resolve_conf_fn, + "network_conf_dir": network_conf_dir, + }, + } + + def __init__(self, name, cfg, paths): + distros.Distro.__init__(self, name, cfg, paths) + self._runner = helpers.Runners(paths) + self.osfamily = "aosc" + 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 _write_hostname(self, hostname, filename): + if filename.endswith("/previous-hostname"): + conf = HostnameConf("") + conf.set_hostname(hostname) + util.write_file(filename, str(conf), 0o644) + create_hostname_file = util.get_cfg_option_bool( + self._cfg, "create_hostname_file", True + ) + if create_hostname_file: + subp.subp(["hostnamectl", "set-hostname", str(hostname)]) + else: + subp.subp( + [ + "hostnamectl", + "set-hostname", + "--transient", + str(hostname), + ] + ) + LOG.info("create_hostname_file is False; hostname set transiently") + + def _read_hostname(self, filename, default=None): + if filename.endswith("/previous-hostname"): + return util.load_text_file(filename).strip() + (out, _err) = subp.subp(["hostname"]) + out = out.strip() + if len(out): + return out + else: + return default + + def _read_system_hostname(self): + sys_hostname = self._read_hostname(self.hostname_conf_fn) + return (self.hostname_conf_fn, sys_hostname) + + def set_timezone(self, tz): + tz_file = self._find_tz_file(tz) + util.del_file(self.tz_local_fn) + util.sym_link(tz_file, self.tz_local_fn) + + def package_command(self, command, args=None, pkgs=None): + if pkgs is None: + pkgs = [] + + cmd = ["oma"] + if command: + cmd.append(command) + cmd.append("-y") + cmd.extend(pkgs) + + subp.subp(cmd, capture=False) + + def install_packages(self, pkglist: PackageList): + self.package_command("install", pkgs=pkglist) + + def update_package_sources(self): + self._runner.run( + "update-sources", + self.package_command, + "refresh", + freq=PER_INSTANCE, + ) diff --git a/cloudinit/util.py b/cloudinit/util.py index 4c38c089156..9a3a3921505 100644 --- a/cloudinit/util.py +++ b/cloudinit/util.py @@ -651,6 +651,7 @@ def _get_variant(info): if linux_dist in ( "almalinux", "alpine", + "aosc", "arch", "azurelinux", "centos", diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl index 78b1ba9469a..0aa382f78a4 100644 --- a/config/cloud.cfg.tmpl +++ b/config/cloud.cfg.tmpl @@ -11,7 +11,7 @@ "netbsd": "NetBSD", "openbsd": "openBSD", "openmandriva": "OpenMandriva admin", "photon": "PhotonOS", "ubuntu": "Ubuntu", "unknown": "Ubuntu"}) %} -{% set groups = ({"alpine": "adm, wheel", "arch": "wheel, users", +{% set groups = ({"alpine": "adm, wheel", "aosc": "wheel", "arch": "wheel, users", "azurelinux": "wheel", "debian": "adm, audio, cdrom, dialout, dip, floppy, netdev, plugdev, sudo, video", "gentoo": "users, wheel", "mariner": "wheel", @@ -220,7 +220,7 @@ cloud_final_modules: # (not accessible to handlers/transforms) system_info: # This will affect which distro class gets used -{% if variant in ["alpine", "amazon", "arch", "azurelinux", "debian", "fedora", +{% if variant in ["alpine", "amazon", "aosc", "arch", "azurelinux", "debian", "fedora", "freebsd", "gentoo", "mariner", "netbsd", "openbsd", "OpenCloudOS", "openeuler", "openmandriva", "photon", "suse", "TencentOS", "ubuntu"] or is_rhel %} @@ -238,7 +238,7 @@ system_info: {% else %} name: {{ variant }} {% endif %} -{% if variant in ["alpine", "amazon", "arch", "azurelinux", "debian", "fedora", +{% if variant in ["alpine", "amazon", "aosc", "arch", "azurelinux", "debian", "fedora", "gentoo", "mariner", "OpenCloudOS", "openeuler", "openmandriva", "photon", "suse", "TencentOS", "ubuntu", "unknown"] @@ -320,7 +320,7 @@ system_info: # Automatically discover the best ntp_client ntp_client: auto {% endif %} -{% if variant in ["alpine", "amazon", "arch", "azurelinux", "debian", "fedora", +{% if variant in ["alpine", "amazon", "aosc", "arch", "azurelinux", "debian", "fedora", "gentoo", "mariner", "OpenCloudOS", "openeuler", "openmandriva", "photon", "suse", "TencentOS", "ubuntu", "unknown"] @@ -368,7 +368,7 @@ system_info: {% endif %} {% if variant in ["debian", "ubuntu", "unknown"] %} ssh_svcname: ssh -{% elif variant in ["alpine", "amazon", "arch", "azurelinux", "fedora", +{% elif variant in ["alpine", "amazon", "aosc", "arch", "azurelinux", "fedora", "gentoo", "mariner", "OpenCloudOS", "openeuler", "openmandriva", "photon", "suse", "TencentOS"] or is_rhel %} diff --git a/tests/unittests/distros/test_aosc.py b/tests/unittests/distros/test_aosc.py new file mode 100644 index 00000000000..26f7ed54c9c --- /dev/null +++ b/tests/unittests/distros/test_aosc.py @@ -0,0 +1,14 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +from cloudinit import util +from tests.unittests.distros import _get_distro +from tests.unittests.helpers import CiTestCase + + +class TestArch(CiTestCase): + def test_get_distro(self): + distro = _get_distro("aosc") + hostname = "myhostname" + hostfile = self.tmp_path("hostfile") + distro._write_hostname(hostname, hostfile) + self.assertEqual(hostname + "\n", util.load_text_file(hostfile)) diff --git a/tools/.github-cla-signers b/tools/.github-cla-signers index c4a7c84c6fd..6a6db18809d 100644 --- a/tools/.github-cla-signers +++ b/tools/.github-cla-signers @@ -100,6 +100,7 @@ klausenbusk KsenijaS landon912 ld9379435 +leavelet licebmi linitio LKHN diff --git a/tools/render-template b/tools/render-template index c3af642a08f..78beeecb2cf 100755 --- a/tools/render-template +++ b/tools/render-template @@ -14,6 +14,7 @@ def main(): "almalinux", "alpine", "amazon", + "aosc", "arch", "azurelinux", "benchmark", From fc5258fde95b09aa585eebda2031fc2c3eb80cce Mon Sep 17 00:00:00 2001 From: leavelet Date: Tue, 21 May 2024 23:10:07 +0800 Subject: [PATCH 2/5] docs: Add AOSC to supported distros --- doc/rtd/reference/distros.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/rtd/reference/distros.rst b/doc/rtd/reference/distros.rst index 59309ece211..d54cb889153 100644 --- a/doc/rtd/reference/distros.rst +++ b/doc/rtd/reference/distros.rst @@ -7,6 +7,7 @@ Unix family of operating systems. See the complete list below. * AlmaLinux * Alpine Linux +* AOSC OS * Arch Linux * CentOS * CloudLinux From c364341a2a3a8d0c1beefacec68a9a4bb7532f80 Mon Sep 17 00:00:00 2001 From: leavelet Date: Wed, 3 Jul 2024 12:04:18 +0800 Subject: [PATCH 3/5] fix: fix test and hostnamectl --- cloudinit/distros/aosc.py | 58 +++++++++++++++++++--------- tests/unittests/distros/test_aosc.py | 8 +--- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/cloudinit/distros/aosc.py b/cloudinit/distros/aosc.py index 69f83d3f399..e3d23c7820c 100644 --- a/cloudinit/distros/aosc.py +++ b/cloudinit/distros/aosc.py @@ -6,8 +6,9 @@ import logging from cloudinit import distros, helpers, subp, util -from cloudinit.distros import PackageList, rhel_util +from cloudinit.distros import PackageList from cloudinit.distros.parsers.hostname import HostnameConf +from cloudinit.distros.parsers.sys_conf import SysConf from cloudinit.settings import PER_INSTANCE LOG = logging.getLogger(__name__) @@ -34,23 +35,12 @@ def __init__(self, name, cfg, paths): 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) + if not out_fn: + out_fn = self.systemd_locale_conf_fn + locale_cfg = { + "LANG": locale, + } + update_locale_conf(out_fn, locale_cfg) def _write_hostname(self, hostname, filename): if filename.endswith("/previous-hostname"): @@ -114,3 +104,35 @@ def update_package_sources(self): "refresh", freq=PER_INSTANCE, ) + + +def read_locale_conf(sys_path): + exists = False + try: + contents = util.load_text_file(sys_path).splitlines() + exists = True + except IOError: + contents = [] + return (exists, SysConf(contents)) + + +def update_locale_conf(sys_path, locale_cfg): + if not locale_cfg: + return + (exists, contents) = read_locale_conf(sys_path) + updated_am = 0 + for (k, v) in locale_cfg.items(): + if v is None: + continue + v = str(v) + if len(v) == 0: + continue + contents[k] = v + updated_am += 1 + if updated_am: + lines = [ + str(contents), + ] + if not exists: + lines.insert(0, util.make_header()) + util.write_file(sys_path, "\n".join(lines) + "\n", 0o644) diff --git a/tests/unittests/distros/test_aosc.py b/tests/unittests/distros/test_aosc.py index 26f7ed54c9c..e8a66b7aef2 100644 --- a/tests/unittests/distros/test_aosc.py +++ b/tests/unittests/distros/test_aosc.py @@ -1,14 +1,10 @@ # This file is part of cloud-init. See LICENSE file for license information. -from cloudinit import util from tests.unittests.distros import _get_distro from tests.unittests.helpers import CiTestCase -class TestArch(CiTestCase): +class TestAOSC(CiTestCase): def test_get_distro(self): distro = _get_distro("aosc") - hostname = "myhostname" - hostfile = self.tmp_path("hostfile") - distro._write_hostname(hostname, hostfile) - self.assertEqual(hostname + "\n", util.load_text_file(hostfile)) + self.assertEqual(distro.osfamily, "aosc") From 20457084f943c1d4d74bfb8dde55e691e3d30c70 Mon Sep 17 00:00:00 2001 From: leavelet Date: Wed, 3 Jul 2024 18:53:43 +0800 Subject: [PATCH 4/5] fix: fix test_wb_schema_subcommand for aosc --- tests/unittests/test_cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unittests/test_cli.py b/tests/unittests/test_cli.py index 3a92d29e261..6ab6d496b16 100644 --- a/tests/unittests/test_cli.py +++ b/tests/unittests/test_cli.py @@ -319,7 +319,8 @@ def test_wb_schema_subcommand_parser(self, m_read_cfg, capsys): ["all"], [ "**Supported distros:** all", - "**Supported distros:** almalinux, alpine, azurelinux, " + "**Supported distros:** " + "almalinux, alpine, aosc, azurelinux, " "centos, cloudlinux, cos, debian, eurolinux, fedora, " "freebsd, mariner, miraclelinux, openbsd, openeuler, " "OpenCloudOS, openmandriva, opensuse, opensuse-microos, " From 0a81d2449498fd4a0768fa20fdb021b868ddb6ba Mon Sep 17 00:00:00 2001 From: leavelet Date: Wed, 3 Jul 2024 18:54:34 +0800 Subject: [PATCH 5/5] fix: change net config for aosc to sysconfig --- cloudinit/distros/aosc.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/cloudinit/distros/aosc.py b/cloudinit/distros/aosc.py index e3d23c7820c..0460c740d5c 100644 --- a/cloudinit/distros/aosc.py +++ b/cloudinit/distros/aosc.py @@ -17,21 +17,31 @@ class Distro(distros.Distro): systemd_locale_conf_fn = "/etc/locale.conf" init_cmd = ["systemctl"] - network_conf_dir = "/etc/systemd/network/" + network_conf_dir = "/etc/sysconfig/network" resolve_conf_fn = "/etc/systemd/resolved.conf" tz_local_fn = "/etc/localtime" + dhclient_lease_directory = "/var/lib/NetworkManager" + dhclient_lease_file_regex = r"dhclient-[\w-]+\.lease" + renderer_configs = { - "networkd": { - "resolv_conf_fn": resolve_conf_fn, - "network_conf_dir": network_conf_dir, - }, + "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", + }, + } } + prefer_fqdn = False + def __init__(self, name, cfg, paths): distros.Distro.__init__(self, name, cfg, paths) self._runner = helpers.Runners(paths) self.osfamily = "aosc" + self.default_locale = "en_US.UTF-8" cfg["ssh_svcname"] = "sshd" def apply_locale(self, locale, out_fn=None):