diff --git a/Fix-the-error-level-logs-displayed-for-the-cloud-init-local-service.patch b/Fix-the-error-level-logs-displayed-for-the-cloud-init-local-service.patch index 91064ca6ef565e18f47c49325d2eb3e797b054fa..40523d18734fcafb3a4ac03d2d7e345ec157fcbc 100644 --- a/Fix-the-error-level-logs-displayed-for-the-cloud-init-local-service.patch +++ b/Fix-the-error-level-logs-displayed-for-the-cloud-init-local-service.patch @@ -13,18 +13,17 @@ Reference:https://bugs.almalinux.org/view.php?id=32&nbn=1 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py -index 0a5d481..17ba3c5 100644 +index 90a4eb9..443a5da 100644 --- a/cloudinit/net/sysconfig.py +++ b/cloudinit/net/sysconfig.py -@@ -19,7 +19,7 @@ from .network_state import ( - - LOG = logging.getLogger(__name__) - NM_CFG_FILE = "/etc/NetworkManager/NetworkManager.conf" --KNOWN_DISTROS = ['centos', 'fedora', 'rhel', 'suse'] -+KNOWN_DISTROS = ['centos', 'fedora', 'rhel', 'suse', 'linux'] - - - def _make_header(sep='#'): --- -1.8.3.1 - +@@ -28,7 +28,7 @@ KNOWN_DISTROS = [ + "eurolinux", + "fedora", + "miraclelinux", +- "openEuler", ++ "openeuler", + "rhel", + "rocky", + "suse", +-- +2.33.0 diff --git a/add-variable-to-forbid-tmp-dir.patch b/add-variable-to-forbid-tmp-dir.patch index 690fea7bbb8683547a35dc7647f455b93824a7d3..abe7521ad5af1b69078dff769e608d5211945fe1 100644 --- a/add-variable-to-forbid-tmp-dir.patch +++ b/add-variable-to-forbid-tmp-dir.patch @@ -7,25 +7,25 @@ reason: add variable to forbid temporary directory Signed-off-by: chengquan --- - setup.py | 15 ++++- - 1 files changed, 12 insertions(+), 3 deletions(-) + setup.py | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py -index bd02fac..a22737c 100755 +index a81c1e9..e4e5fdb 100755 --- a/setup.py +++ b/setup.py -@@ -75,6 +75,8 @@ def read_requires(): +@@ -79,6 +79,8 @@ def read_requires(): deps = subprocess.check_output(cmd) - return deps.decode('utf-8').splitlines() - + return deps.decode("utf-8").splitlines() + +# add variable to forbid tmp dir +num = 0 - + def render_tmpl(template, mode=None): """render template into a tmpdir under same dir as setup.py -@@ -96,7 +98,10 @@ def render_tmpl(template, mode=None): +@@ -100,7 +102,10 @@ def render_tmpl(template, mode=None): return template - + topdir = os.path.dirname(sys.argv[0]) - tmpd = tempfile.mkdtemp(dir=topdir, prefix=RENDERED_TMPD_PREFIX) + global num @@ -35,26 +35,29 @@ index bd02fac..a22737c 100755 atexit.register(shutil.rmtree, tmpd) bname = os.path.basename(template).rstrip(tmpl_ext) fpath = os.path.join(tmpd, bname) -@@ -111,6 +116,10 @@ def render_tmpl(template, mode=None): +@@ -124,6 +129,9 @@ def render_tmpl(template, mode=None): # return path relative to setup.py return os.path.join(os.path.basename(tmpd), bname) - + +def sort_files(file_list): + file_list.sort() + return file_list -+ + # User can set the variant for template rendering - if '--distro' in sys.argv: - idx = sys.argv.index('--distro') -@@ -126,9 +135,9 @@ INITSYS_FILES = { - 'sysvinit_openrc': [f for f in glob('sysvinit/gentoo/*') if is_f(f)], - 'sysvinit_suse': [f for f in glob('sysvinit/suse/*') if is_f(f)], - 'systemd': [render_tmpl(f) -- for f in (glob('systemd/*.tmpl') + -+ for f in sort_files((glob('systemd/*.tmpl') + - glob('systemd/*.service') + -- glob('systemd/*.target')) -+ glob('systemd/*.target'))) - if (is_f(f) and not is_generator(f))], - 'systemd.generators': [ - render_tmpl(f, mode=0o755) + if "--distro" in sys.argv: +@@ -142,11 +150,11 @@ INITSYS_FILES = { + "systemd": [ + render_tmpl(f) + for f in ( +- glob("systemd/*.tmpl") ++ sort_files((glob('systemd/*.tmpl') + + glob("systemd/*.service") + + glob("systemd/*.socket") + + glob("systemd/*.target") +- ) ++ ))) + if (is_f(f) and not is_generator(f)) + ], + "systemd.generators": [ +-- +2.27.0 \ No newline at end of file diff --git a/backport-CVE-2021-3429-write-passwords-only-to-serial-console-lock-down-clo.patch b/backport-CVE-2021-3429-write-passwords-only-to-serial-console-lock-down-clo.patch deleted file mode 100644 index 8d26a7c974fdd82fcf2f392d8f35540b66c87843..0000000000000000000000000000000000000000 --- a/backport-CVE-2021-3429-write-passwords-only-to-serial-console-lock-down-clo.patch +++ /dev/null @@ -1,350 +0,0 @@ -From b794d426b9ab43ea9d6371477466070d86e10668 Mon Sep 17 00:00:00 2001 -From: Daniel Watkins -Date: Fri, 19 Mar 2021 10:06:42 -0400 -Subject: [PATCH] write passwords only to serial console, lock down - cloud-init-output.log (#847) - -Prior to this commit, when a user specified configuration which would -generate random passwords for users, cloud-init would cause those -passwords to be written to the serial console by emitting them on -stderr. In the default configuration, any stdout or stderr emitted by -cloud-init is also written to `/var/log/cloud-init-output.log`. This -file is world-readable, meaning that those randomly-generated passwords -were available to be read by any user with access to the system. This -presents an obvious security issue. - -This commit responds to this issue in two ways: - -* We address the direct issue by moving from writing the passwords to - sys.stderr to writing them directly to /dev/console (via - util.multi_log); this means that the passwords will never end up in - cloud-init-output.log -* To avoid future issues like this, we also modify the logging code so - that any files created in a log sink subprocess will only be - owner/group readable and, if it exists, will be owned by the adm - group. This results in `/var/log/cloud-init-output.log` no longer - being world-readable, meaning that if there are other parts of the - codebase that are emitting sensitive data intended for the serial - console, that data is no longer available to all users of the system. - -LP: #1918303 ---- - cloudinit/config/cc_set_passwords.py | 5 +- - cloudinit/config/tests/test_set_passwords.py | 40 +++++++++---- - cloudinit/tests/test_util.py | 56 +++++++++++++++++++ - cloudinit/util.py | 38 +++++++++++-- - tests/integration_tests/test_logging.py | 22 ++++++++ - tests/unittests/test_util.py | 4 ++ - 6 files changed, 173 insertions(+), 16 deletions(-) - create mode 100644 tests/integration_tests/test_logging.py - -diff --git a/cloudinit/config/cc_set_passwords.py b/cloudinit/config/cc_set_passwords.py -index d6b5682db4..433de751fa 100755 ---- a/cloudinit/config/cc_set_passwords.py -+++ b/cloudinit/config/cc_set_passwords.py -@@ -78,7 +78,6 @@ - """ - - import re --import sys - - from cloudinit.distros import ug_util - from cloudinit import log as logging -@@ -214,7 +213,9 @@ def handle(_name, cfg, cloud, log, args): - if len(randlist): - blurb = ("Set the following 'random' passwords\n", - '\n'.join(randlist)) -- sys.stderr.write("%s\n%s\n" % blurb) -+ util.multi_log( -+ "%s\n%s\n" % blurb, stderr=False, fallback_to_stdout=False -+ ) - - if expire: - expired_users = [] -diff --git a/cloudinit/config/tests/test_set_passwords.py b/cloudinit/config/tests/test_set_passwords.py -index daa1ef518f..bbe2ee8faa 100644 ---- a/cloudinit/config/tests/test_set_passwords.py -+++ b/cloudinit/config/tests/test_set_passwords.py -@@ -74,10 +74,6 @@ class TestSetPasswordsHandle(CiTestCase): - - with_logs = True - -- def setUp(self): -- super(TestSetPasswordsHandle, self).setUp() -- self.add_patch('cloudinit.config.cc_set_passwords.sys.stderr', 'm_err') -- - def test_handle_on_empty_config(self, *args): - """handle logs that no password has changed when config is empty.""" - cloud = self.tmp_cloud(distro='ubuntu') -@@ -129,10 +125,12 @@ def test_bsd_calls_custom_pw_cmds_to_set_and_expire_passwords( - mock.call(['pw', 'usermod', 'ubuntu', '-p', '01-Jan-1970'])], - m_subp.call_args_list) - -+ @mock.patch(MODPATH + "util.multi_log") - @mock.patch(MODPATH + "util.is_BSD") - @mock.patch(MODPATH + "subp.subp") -- def test_handle_on_chpasswd_list_creates_random_passwords(self, m_subp, -- m_is_bsd): -+ def test_handle_on_chpasswd_list_creates_random_passwords( -+ self, m_subp, m_is_bsd, m_multi_log -+ ): - """handle parses command set random passwords.""" - m_is_bsd.return_value = False - cloud = self.tmp_cloud(distro='ubuntu') -@@ -146,10 +144,32 @@ def test_handle_on_chpasswd_list_creates_random_passwords(self, m_subp, - self.assertIn( - 'DEBUG: Handling input for chpasswd as list.', - self.logs.getvalue()) -- self.assertNotEqual( -- [mock.call(['chpasswd'], -- '\n'.join(valid_random_pwds) + '\n')], -- m_subp.call_args_list) -+ -+ self.assertEqual(1, m_subp.call_count) -+ args, _kwargs = m_subp.call_args -+ self.assertEqual(["chpasswd"], args[0]) -+ -+ stdin = args[1] -+ user_pass = { -+ user: password -+ for user, password -+ in (line.split(":") for line in stdin.splitlines()) -+ } -+ -+ self.assertEqual(1, m_multi_log.call_count) -+ self.assertEqual( -+ mock.call(mock.ANY, stderr=False, fallback_to_stdout=False), -+ m_multi_log.call_args -+ ) -+ -+ self.assertEqual(set(["root", "ubuntu"]), set(user_pass.keys())) -+ written_lines = m_multi_log.call_args[0][0].splitlines() -+ for password in user_pass.values(): -+ for line in written_lines: -+ if password in line: -+ break -+ else: -+ self.fail("Password not emitted to console") - - - # vi: ts=4 expandtab -diff --git a/cloudinit/tests/test_util.py b/cloudinit/tests/test_util.py -index b7a302f1cc..e811917e01 100644 ---- a/cloudinit/tests/test_util.py -+++ b/cloudinit/tests/test_util.py -@@ -851,4 +851,60 @@ def test_static_parameters_are_passed(self, m_write_file): - assert "ab" == kwargs["omode"] - - -+@mock.patch("cloudinit.util.grp.getgrnam") -+@mock.patch("cloudinit.util.os.setgid") -+@mock.patch("cloudinit.util.os.umask") -+class TestRedirectOutputPreexecFn: -+ """This tests specifically the preexec_fn used in redirect_output.""" -+ -+ @pytest.fixture(params=["outfmt", "errfmt"]) -+ def preexec_fn(self, request): -+ """A fixture to gather the preexec_fn used by redirect_output. -+ -+ This enables simpler direct testing of it, and parameterises any tests -+ using it to cover both the stdout and stderr code paths. -+ """ -+ test_string = "| piped output to invoke subprocess" -+ if request.param == "outfmt": -+ args = (test_string, None) -+ elif request.param == "errfmt": -+ args = (None, test_string) -+ with mock.patch("cloudinit.util.subprocess.Popen") as m_popen: -+ util.redirect_output(*args) -+ -+ assert 1 == m_popen.call_count -+ _args, kwargs = m_popen.call_args -+ assert "preexec_fn" in kwargs, "preexec_fn not passed to Popen" -+ return kwargs["preexec_fn"] -+ -+ def test_preexec_fn_sets_umask( -+ self, m_os_umask, _m_setgid, _m_getgrnam, preexec_fn -+ ): -+ """preexec_fn should set a mask that avoids world-readable files.""" -+ preexec_fn() -+ -+ assert [mock.call(0o037)] == m_os_umask.call_args_list -+ -+ def test_preexec_fn_sets_group_id_if_adm_group_present( -+ self, _m_os_umask, m_setgid, m_getgrnam, preexec_fn -+ ): -+ """We should setgrp to adm if present, so files are owned by them.""" -+ fake_group = mock.Mock(gr_gid=mock.sentinel.gr_gid) -+ m_getgrnam.return_value = fake_group -+ -+ preexec_fn() -+ -+ assert [mock.call("adm")] == m_getgrnam.call_args_list -+ assert [mock.call(mock.sentinel.gr_gid)] == m_setgid.call_args_list -+ -+ def test_preexec_fn_handles_absent_adm_group_gracefully( -+ self, _m_os_umask, m_setgid, m_getgrnam, preexec_fn -+ ): -+ """We should handle an absent adm group gracefully.""" -+ m_getgrnam.side_effect = KeyError("getgrnam(): name not found: 'adm'") -+ -+ preexec_fn() -+ -+ assert 0 == m_setgid.call_count -+ - # vi: ts=4 expandtab -diff --git a/cloudinit/util.py b/cloudinit/util.py -index 769f3425ee..4e0a72db86 100644 ---- a/cloudinit/util.py -+++ b/cloudinit/util.py -@@ -359,7 +359,7 @@ def find_modules(root_dir): - - - def multi_log(text, console=True, stderr=True, -- log=None, log_level=logging.DEBUG): -+ log=None, log_level=logging.DEBUG, fallback_to_stdout=True): - if stderr: - sys.stderr.write(text) - if console: -@@ -368,7 +368,7 @@ def multi_log(text, console=True, stderr=True, - with open(conpath, 'w') as wfh: - wfh.write(text) - wfh.flush() -- else: -+ elif fallback_to_stdout: - # A container may lack /dev/console (arguably a container bug). If - # it does not exist, then write output to stdout. this will result - # in duplicate stderr and stdout messages if stderr was True. -@@ -623,6 +623,26 @@ def redirect_output(outfmt, errfmt, o_out=None, o_err=None): - if not o_err: - o_err = sys.stderr - -+ # pylint: disable=subprocess-popen-preexec-fn -+ def set_subprocess_umask_and_gid(): -+ """Reconfigure umask and group ID to create output files securely. -+ -+ This is passed to subprocess.Popen as preexec_fn, so it is executed in -+ the context of the newly-created process. It: -+ -+ * sets the umask of the process so created files aren't world-readable -+ * if an adm group exists in the system, sets that as the process' GID -+ (so that the created file(s) are owned by root:adm) -+ """ -+ os.umask(0o037) -+ try: -+ group_id = grp.getgrnam("adm").gr_gid -+ except KeyError: -+ # No adm group, don't set a group -+ pass -+ else: -+ os.setgid(group_id) -+ - if outfmt: - LOG.debug("Redirecting %s to %s", o_out, outfmt) - (mode, arg) = outfmt.split(" ", 1) -@@ -632,7 +652,12 @@ def redirect_output(outfmt, errfmt, o_out=None, o_err=None): - owith = "wb" - new_fp = open(arg, owith) - elif mode == "|": -- proc = subprocess.Popen(arg, shell=True, stdin=subprocess.PIPE) -+ proc = subprocess.Popen( -+ arg, -+ shell=True, -+ stdin=subprocess.PIPE, -+ preexec_fn=set_subprocess_umask_and_gid, -+ ) - new_fp = proc.stdin - else: - raise TypeError("Invalid type for output format: %s" % outfmt) -@@ -654,7 +679,12 @@ def redirect_output(outfmt, errfmt, o_out=None, o_err=None): - owith = "wb" - new_fp = open(arg, owith) - elif mode == "|": -- proc = subprocess.Popen(arg, shell=True, stdin=subprocess.PIPE) -+ proc = subprocess.Popen( -+ arg, -+ shell=True, -+ stdin=subprocess.PIPE, -+ preexec_fn=set_subprocess_umask_and_gid, -+ ) - new_fp = proc.stdin - else: - raise TypeError("Invalid type for error format: %s" % errfmt) -diff --git a/tests/integration_tests/modules/test_set_password.py b/tests/integration_tests/modules/test_set_password.py -index b13f76fbfd..d7cf91a57b 100644 ---- a/tests/integration_tests/modules/test_set_password.py -+++ b/tests/integration_tests/modules/test_set_password.py -@@ -116,6 +116,30 @@ def test_random_passwords_set_correctly(self, class_client): - # Which are not the same - assert shadow_users["harry"] != shadow_users["dick"] - -+ def test_random_passwords_not_stored_in_cloud_init_output_log( -+ self, class_client -+ ): -+ """We should not emit passwords to the in-instance log file. -+ -+ LP: #1918303 -+ """ -+ cloud_init_output = class_client.read_from_file( -+ "/var/log/cloud-init-output.log" -+ ) -+ assert "dick:" not in cloud_init_output -+ assert "harry:" not in cloud_init_output -+ -+ def test_random_passwords_emitted_to_serial_console(self, class_client): -+ """We should emit passwords to the serial console. (LP: #1918303)""" -+ try: -+ console_log = class_client.instance.console_log() -+ except NotImplementedError: -+ # Assume that an exception here means that we can't use the console -+ # log -+ pytest.skip("NotImplementedError when requesting console log") -+ assert "dick:" in console_log -+ assert "harry:" in console_log -+ - def test_explicit_password_set_correctly(self, class_client): - """Test that an explicitly-specified password is set correctly.""" - shadow_users, _ = self._fetch_and_parse_etc_shadow(class_client) -diff --git a/tests/integration_tests/test_logging.py b/tests/integration_tests/test_logging.py -new file mode 100644 -index 0000000000..b31a043482 ---- /dev/null -+++ b/tests/integration_tests/test_logging.py -@@ -0,0 +1,22 @@ -+"""Integration tests relating to cloud-init's logging.""" -+ -+ -+class TestVarLogCloudInitOutput: -+ """Integration tests relating to /var/log/cloud-init-output.log.""" -+ -+ def test_var_log_cloud_init_output_not_world_readable(self, client): -+ """ -+ The log can contain sensitive data, it shouldn't be world-readable. -+ -+ LP: #1918303 -+ """ -+ # Check the file exists -+ assert client.execute("test -f /var/log/cloud-init-output.log").ok -+ -+ # Check its permissions are as we expect -+ perms, user, group = client.execute( -+ "stat -c %a:%U:%G /var/log/cloud-init-output.log" -+ ).split(":") -+ assert "640" == perms -+ assert "root" == user -+ assert "adm" == group -diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py -index 857629f1c4..e52920010a 100644 ---- a/tests/unittests/test_util.py -+++ b/tests/unittests/test_util.py -@@ -572,6 +572,10 @@ def test_logs_go_to_stdout_if_console_does_not_exist(self): - util.multi_log(logged_string) - self.assertEqual(logged_string, self.stdout.getvalue()) - -+ def test_logs_dont_go_to_stdout_if_fallback_to_stdout_is_false(self): -+ util.multi_log('something', fallback_to_stdout=False) -+ self.assertEqual('', self.stdout.getvalue()) -+ - def test_logs_go_to_log_if_given(self): - log = mock.MagicMock() - logged_string = 'something very important' diff --git a/backport-add-Requires-cloud-init-hotplugd.socket-in-cloud-init-hotplugd.service-file.patch b/backport-add-Requires-cloud-init-hotplugd.socket-in-cloud-init-hotplugd.service-file.patch new file mode 100644 index 0000000000000000000000000000000000000000..b5d3bbbc4225e161d0ff0327aa9c86c7d6757af3 --- /dev/null +++ b/backport-add-Requires-cloud-init-hotplugd.socket-in-cloud-init-hotplugd.service-file.patch @@ -0,0 +1,34 @@ +From fca5bb77c251bea6ed7a21e9b9e0b320a01575a9 Mon Sep 17 00:00:00 2001 +From: yangzz-97 <70520104+yangzz-97@users.noreply.github.com> +Date: Fri, 18 Mar 2022 04:12:31 +0800 +Subject: [PATCH] add Requires=cloud-init-hotplugd.socket in + cloud-init-hotplugd.service file (#1335) + +Signed-off-by: yangzz-97 +--- + systemd/cloud-init-hotplugd.service | 1 + + tools/.github-cla-signers | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/systemd/cloud-init-hotplugd.service b/systemd/cloud-init-hotplugd.service +index b64632efe9..10962d549e 100644 +--- a/systemd/cloud-init-hotplugd.service ++++ b/systemd/cloud-init-hotplugd.service +@@ -12,6 +12,7 @@ + [Unit] + Description=cloud-init hotplug hook daemon + After=cloud-init-hotplugd.socket ++Requires=cloud-init-hotplugd.socket + + [Service] + Type=simple +diff --git a/tools/.github-cla-signers b/tools/.github-cla-signers +index e205d6ea32..27352aba73 100644 +--- a/tools/.github-cla-signers ++++ b/tools/.github-cla-signers +@@ -92,4 +92,5 @@ Vultaire + WebSpider + xiachen-rh + xnox ++yangzz-97 + zhuzaifangxuele diff --git a/backport-net-exclude-OVS-internal-interfaces-in-get_interface.patch b/backport-net-exclude-OVS-internal-interfaces-in-get_interface.patch deleted file mode 100644 index ac56366d86f6b44c553895a6b45880b7569ecdc4..0000000000000000000000000000000000000000 --- a/backport-net-exclude-OVS-internal-interfaces-in-get_interface.patch +++ /dev/null @@ -1,496 +0,0 @@ -From 121bc04cdf0e6732fe143b7419131dc250c13384 Mon Sep 17 00:00:00 2001 -From: Daniel Watkins -Date: Mon, 8 Mar 2021 12:50:57 -0500 -Subject: [PATCH] net: exclude OVS internal interfaces in get_interfaces (#829) - -`get_interfaces` is used to in two ways, broadly: firstly, to determine -the available interfaces when converting cloud network configuration -formats to cloud-init's network configuration formats; and, secondly, to -ensure that any interfaces which are specified in network configuration -are (a) available, and (b) named correctly. The first of these is -unaffected by this commit, as no clouds support Open vSwitch -configuration in their network configuration formats. - -For the second, we check that MAC addresses of physical devices are -unique. In some OVS configurations, there are OVS-created devices which -have duplicate MAC addresses, either with each other or with physical -devices. As these interfaces are created by OVS, we can be confident -that (a) they will be available when appropriate, and (b) that OVS will -name them correctly. As such, this commit excludes any OVS-internal -interfaces from the set of interfaces returned by `get_interfaces`. - -LP: #1912844 ---- - cloudinit/net/__init__.py | 62 +++++++++++ - cloudinit/net/tests/test_init.py | 119 +++++++++++++++++++++ - cloudinit/sources/helpers/tests/test_openstack.py | 5 + - cloudinit/sources/tests/test_oracle.py | 4 + - tests/integration_tests/bugs/test_lp1912844.py | 103 ++++++++++++++++++ - .../unittests/test_datasource/test_configdrive.py | 8 ++ - tests/unittests/test_net.py | 20 ++++ - 7 files changed, 321 insertions(+) - create mode 100644 tests/integration_tests/bugs/test_lp1912844.py - -diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py -index de65e7a..385b7bc 100644 ---- a/cloudinit/net/__init__.py -+++ b/cloudinit/net/__init__.py -@@ -6,6 +6,7 @@ - # This file is part of cloud-init. See LICENSE file for license information. - - import errno -+import functools - import ipaddress - import logging - import os -@@ -19,6 +20,19 @@ from cloudinit.url_helper import UrlError, readurl - LOG = logging.getLogger(__name__) - SYS_CLASS_NET = "/sys/class/net/" - DEFAULT_PRIMARY_INTERFACE = 'eth0' -+OVS_INTERNAL_INTERFACE_LOOKUP_CMD = [ -+ "ovs-vsctl", -+ "--format", -+ "csv", -+ "--no-headings", -+ "--timeout", -+ "10", -+ "--columns", -+ "name", -+ "find", -+ "interface", -+ "type=internal", -+] - - - def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): -@@ -133,6 +147,52 @@ def master_is_openvswitch(devname): - return os.path.exists(ovs_path) - - -+@functools.lru_cache(maxsize=None) -+def openvswitch_is_installed() -> bool: -+ """Return a bool indicating if Open vSwitch is installed in the system.""" -+ ret = bool(subp.which("ovs-vsctl")) -+ if not ret: -+ LOG.debug( -+ "ovs-vsctl not in PATH; not detecting Open vSwitch interfaces" -+ ) -+ return ret -+ -+ -+@functools.lru_cache(maxsize=None) -+def get_ovs_internal_interfaces() -> list: -+ """Return a list of the names of OVS internal interfaces on the system. -+ -+ These will all be strings, and are used to exclude OVS-specific interface -+ from cloud-init's network configuration handling. -+ """ -+ try: -+ out, _err = subp.subp(OVS_INTERNAL_INTERFACE_LOOKUP_CMD) -+ except subp.ProcessExecutionError as exc: -+ if "database connection failed" in exc.stderr: -+ LOG.info( -+ "Open vSwitch is not yet up; no interfaces will be detected as" -+ " OVS-internal" -+ ) -+ return [] -+ raise -+ else: -+ return out.splitlines() -+ -+ -+def is_openvswitch_internal_interface(devname: str) -> bool: -+ """Returns True if this is an OVS internal interface. -+ -+ If OVS is not installed or not yet running, this will return False. -+ """ -+ if not openvswitch_is_installed(): -+ return False -+ ovs_bridges = get_ovs_internal_interfaces() -+ if devname in ovs_bridges: -+ LOG.debug("Detected %s as an OVS interface", devname) -+ return True -+ return False -+ -+ - def is_netfailover(devname, driver=None): - """ netfailover driver uses 3 nics, master, primary and standby. - this returns True if the device is either the primary or standby -@@ -884,6 +944,8 @@ def get_interfaces(blacklist_drivers=None) -> list: - # skip nics that have no mac (00:00....) - if name != 'lo' and mac == zero_mac[:len(mac)]: - continue -+ if is_openvswitch_internal_interface(name): -+ continue - # skip nics that have drivers blacklisted - driver = device_driver(name) - if driver in blacklist_drivers: -diff --git a/cloudinit/net/tests/test_init.py b/cloudinit/net/tests/test_init.py -index 0535387..946f8ee 100644 ---- a/cloudinit/net/tests/test_init.py -+++ b/cloudinit/net/tests/test_init.py -@@ -391,6 +391,10 @@ class TestGetDeviceList(CiTestCase): - self.assertCountEqual(['eth0', 'eth1'], net.get_devicelist()) - - -+@mock.patch( -+ "cloudinit.net.is_openvswitch_internal_interface", -+ mock.Mock(return_value=False), -+) - class TestGetInterfaceMAC(CiTestCase): - - def setUp(self): -@@ -1224,6 +1228,121 @@ class TestNetFailOver(CiTestCase): - self.assertFalse(net.is_netfailover(devname, driver)) - - -+class TestOpenvswitchIsInstalled: -+ """Test cloudinit.net.openvswitch_is_installed. -+ -+ Uses the ``clear_lru_cache`` local autouse fixture to allow us to test -+ despite the ``lru_cache`` decorator on the unit under test. -+ """ -+ -+ @pytest.fixture(autouse=True) -+ def clear_lru_cache(self): -+ net.openvswitch_is_installed.cache_clear() -+ -+ @pytest.mark.parametrize( -+ "expected,which_return", [(True, "/some/path"), (False, None)] -+ ) -+ @mock.patch("cloudinit.net.subp.which") -+ def test_mirrors_which_result(self, m_which, expected, which_return): -+ m_which.return_value = which_return -+ assert expected == net.openvswitch_is_installed() -+ -+ @mock.patch("cloudinit.net.subp.which") -+ def test_only_calls_which_once(self, m_which): -+ net.openvswitch_is_installed() -+ net.openvswitch_is_installed() -+ assert 1 == m_which.call_count -+ -+ -+@mock.patch("cloudinit.net.subp.subp", return_value=("", "")) -+class TestGetOVSInternalInterfaces: -+ """Test cloudinit.net.get_ovs_internal_interfaces. -+ -+ Uses the ``clear_lru_cache`` local autouse fixture to allow us to test -+ despite the ``lru_cache`` decorator on the unit under test. -+ """ -+ @pytest.fixture(autouse=True) -+ def clear_lru_cache(self): -+ net.get_ovs_internal_interfaces.cache_clear() -+ -+ def test_command_used(self, m_subp): -+ """Test we use the correct command when we call subp""" -+ net.get_ovs_internal_interfaces() -+ -+ assert [ -+ mock.call(net.OVS_INTERNAL_INTERFACE_LOOKUP_CMD) -+ ] == m_subp.call_args_list -+ -+ def test_subp_contents_split_and_returned(self, m_subp): -+ """Test that the command output is appropriately mangled.""" -+ stdout = "iface1\niface2\niface3\n" -+ m_subp.return_value = (stdout, "") -+ -+ assert [ -+ "iface1", -+ "iface2", -+ "iface3", -+ ] == net.get_ovs_internal_interfaces() -+ -+ def test_database_connection_error_handled_gracefully(self, m_subp): -+ """Test that the error indicating OVS is down is handled gracefully.""" -+ m_subp.side_effect = ProcessExecutionError( -+ stderr="database connection failed" -+ ) -+ -+ assert [] == net.get_ovs_internal_interfaces() -+ -+ def test_other_errors_raised(self, m_subp): -+ """Test that only database connection errors are handled.""" -+ m_subp.side_effect = ProcessExecutionError() -+ -+ with pytest.raises(ProcessExecutionError): -+ net.get_ovs_internal_interfaces() -+ -+ def test_only_runs_once(self, m_subp): -+ """Test that we cache the value.""" -+ net.get_ovs_internal_interfaces() -+ net.get_ovs_internal_interfaces() -+ -+ assert 1 == m_subp.call_count -+ -+ -+@mock.patch("cloudinit.net.get_ovs_internal_interfaces") -+@mock.patch("cloudinit.net.openvswitch_is_installed") -+class TestIsOpenVSwitchInternalInterface: -+ def test_false_if_ovs_not_installed( -+ self, m_openvswitch_is_installed, _m_get_ovs_internal_interfaces -+ ): -+ """Test that OVS' absence returns False.""" -+ m_openvswitch_is_installed.return_value = False -+ -+ assert not net.is_openvswitch_internal_interface("devname") -+ -+ @pytest.mark.parametrize( -+ "detected_interfaces,devname,expected_return", -+ [ -+ ([], "devname", False), -+ (["notdevname"], "devname", False), -+ (["devname"], "devname", True), -+ (["some", "other", "devices", "and", "ours"], "ours", True), -+ ], -+ ) -+ def test_return_value_based_on_detected_interfaces( -+ self, -+ m_openvswitch_is_installed, -+ m_get_ovs_internal_interfaces, -+ detected_interfaces, -+ devname, -+ expected_return, -+ ): -+ """Test that the detected interfaces are used correctly.""" -+ m_openvswitch_is_installed.return_value = True -+ m_get_ovs_internal_interfaces.return_value = detected_interfaces -+ assert expected_return == net.is_openvswitch_internal_interface( -+ devname -+ ) -+ -+ - class TestIsIpAddress: - """Tests for net.is_ip_address. - -diff --git a/cloudinit/sources/helpers/tests/test_openstack.py b/cloudinit/sources/helpers/tests/test_openstack.py -index 2bde1e3..95fb974 100644 ---- a/cloudinit/sources/helpers/tests/test_openstack.py -+++ b/cloudinit/sources/helpers/tests/test_openstack.py -@@ -1,10 +1,15 @@ - # This file is part of cloud-init. See LICENSE file for license information. - # ./cloudinit/sources/helpers/tests/test_openstack.py -+from unittest import mock - - from cloudinit.sources.helpers import openstack - from cloudinit.tests import helpers as test_helpers - - -+@mock.patch( -+ "cloudinit.net.is_openvswitch_internal_interface", -+ mock.Mock(return_value=False) -+) - class TestConvertNetJson(test_helpers.CiTestCase): - - def test_phy_types(self): -diff --git a/cloudinit/sources/tests/test_oracle.py b/cloudinit/sources/tests/test_oracle.py -index a7bbdfd..dcf33b9 100644 ---- a/cloudinit/sources/tests/test_oracle.py -+++ b/cloudinit/sources/tests/test_oracle.py -@@ -173,6 +173,10 @@ class TestIsPlatformViable(test_helpers.CiTestCase): - m_read_dmi_data.assert_has_calls([mock.call('chassis-asset-tag')]) - - -+@mock.patch( -+ "cloudinit.net.is_openvswitch_internal_interface", -+ mock.Mock(return_value=False) -+) - class TestNetworkConfigFromOpcImds: - def test_no_secondary_nics_does_not_mutate_input(self, oracle_ds): - oracle_ds._vnics_data = [{}] -diff --git a/tests/integration_tests/bugs/test_lp1912844.py b/tests/integration_tests/bugs/test_lp1912844.py -new file mode 100644 -index 0000000..efafae5 ---- /dev/null -+++ b/tests/integration_tests/bugs/test_lp1912844.py -@@ -0,0 +1,103 @@ -+"""Integration test for LP: #1912844 -+ -+cloud-init should ignore OVS-internal interfaces when performing its own -+interface determination: these interfaces are handled fully by OVS, so -+cloud-init should never need to touch them. -+ -+This test is a semi-synthetic reproducer for the bug. It uses a similar -+network configuration, tweaked slightly to DHCP in a way that will succeed even -+on "failed" boots. The exact bug doesn't reproduce with the NoCloud -+datasource, because it runs at init-local time (whereas the MAAS datasource, -+from the report, runs only at init (network) time): this means that the -+networking code runs before OVS creates its interfaces (which happens after -+init-local but, of course, before networking is up), and so doesn't generate -+the traceback that they cause. We work around this by calling -+``get_interfaces_by_mac` directly in the test code. -+""" -+import pytest -+ -+from tests.integration_tests import random_mac_address -+ -+MAC_ADDRESS = random_mac_address() -+ -+NETWORK_CONFIG = """\ -+bonds: -+ bond0: -+ interfaces: -+ - enp5s0 -+ macaddress: {0} -+ mtu: 1500 -+bridges: -+ ovs-br: -+ interfaces: -+ - bond0 -+ macaddress: {0} -+ mtu: 1500 -+ openvswitch: {{}} -+ dhcp4: true -+ethernets: -+ enp5s0: -+ mtu: 1500 -+ set-name: enp5s0 -+ match: -+ macaddress: {0} -+version: 2 -+vlans: -+ ovs-br.100: -+ id: 100 -+ link: ovs-br -+ mtu: 1500 -+ ovs-br.200: -+ id: 200 -+ link: ovs-br -+ mtu: 1500 -+""".format(MAC_ADDRESS) -+ -+ -+SETUP_USER_DATA = """\ -+#cloud-config -+packages: -+- openvswitch-switch -+""" -+ -+ -+@pytest.fixture -+def ovs_enabled_session_cloud(session_cloud): -+ """A session_cloud wrapper, to use an OVS-enabled image for tests. -+ -+ This implementation is complicated by wanting to use ``session_cloud``s -+ snapshot cleanup/retention logic, to avoid having to reimplement that here. -+ """ -+ old_snapshot_id = session_cloud.snapshot_id -+ with session_cloud.launch( -+ user_data=SETUP_USER_DATA, -+ ) as instance: -+ instance.instance.clean() -+ session_cloud.snapshot_id = instance.snapshot() -+ -+ yield session_cloud -+ -+ try: -+ session_cloud.delete_snapshot() -+ finally: -+ session_cloud.snapshot_id = old_snapshot_id -+ -+ -+@pytest.mark.lxd_vm -+def test_get_interfaces_by_mac_doesnt_traceback(ovs_enabled_session_cloud): -+ """Launch our OVS-enabled image and confirm the bug doesn't reproduce.""" -+ launch_kwargs = { -+ "config_dict": { -+ "user.network-config": NETWORK_CONFIG, -+ "volatile.eth0.hwaddr": MAC_ADDRESS, -+ }, -+ } -+ with ovs_enabled_session_cloud.launch( -+ launch_kwargs=launch_kwargs, -+ ) as client: -+ result = client.execute( -+ "python3 -c" -+ "'from cloudinit.net import get_interfaces_by_mac;" -+ "get_interfaces_by_mac()'" -+ ) -+ assert result.ok -diff --git a/tests/unittests/test_datasource/test_configdrive.py b/tests/unittests/test_datasource/test_configdrive.py -index 6f830cc..2e2b784 100644 ---- a/tests/unittests/test_datasource/test_configdrive.py -+++ b/tests/unittests/test_datasource/test_configdrive.py -@@ -494,6 +494,10 @@ class TestConfigDriveDataSource(CiTestCase): - self.assertEqual('config-disk (/dev/anything)', cfg_ds.subplatform) - - -+@mock.patch( -+ "cloudinit.net.is_openvswitch_internal_interface", -+ mock.Mock(return_value=False) -+) - class TestNetJson(CiTestCase): - def setUp(self): - super(TestNetJson, self).setUp() -@@ -654,6 +658,10 @@ class TestNetJson(CiTestCase): - self.assertEqual(out_data, conv_data) - - -+@mock.patch( -+ "cloudinit.net.is_openvswitch_internal_interface", -+ mock.Mock(return_value=False) -+) - class TestConvertNetworkData(CiTestCase): - - with_logs = True -diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py -index 38d934d..cb636f4 100644 ---- a/tests/unittests/test_net.py -+++ b/tests/unittests/test_net.py -@@ -2933,6 +2933,10 @@ iface eth1 inet dhcp - self.assertEqual(0, mock_settle.call_count) - - -+@mock.patch( -+ "cloudinit.net.is_openvswitch_internal_interface", -+ mock.Mock(return_value=False) -+) - class TestRhelSysConfigRendering(CiTestCase): - - with_logs = True -@@ -3620,6 +3624,10 @@ USERCTL=no - expected, self._render_and_read(network_config=v2data)) - - -+@mock.patch( -+ "cloudinit.net.is_openvswitch_internal_interface", -+ mock.Mock(return_value=False) -+) - class TestOpenSuseSysConfigRendering(CiTestCase): - - with_logs = True -@@ -5037,6 +5045,10 @@ class TestNetRenderers(CiTestCase): - self.assertTrue(result) - - -+@mock.patch( -+ "cloudinit.net.is_openvswitch_internal_interface", -+ mock.Mock(return_value=False) -+) - class TestGetInterfaces(CiTestCase): - _data = {'bonds': ['bond1'], - 'bridges': ['bridge1'], -@@ -5186,6 +5198,10 @@ class TestInterfaceHasOwnMac(CiTestCase): - self.assertFalse(interface_has_own_mac("eth0")) - - -+@mock.patch( -+ "cloudinit.net.is_openvswitch_internal_interface", -+ mock.Mock(return_value=False) -+) - class TestGetInterfacesByMac(CiTestCase): - _data = {'bonds': ['bond1'], - 'bridges': ['bridge1'], -@@ -5342,6 +5358,10 @@ class TestInterfacesSorting(CiTestCase): - ['enp0s3', 'enp0s8', 'enp0s13', 'enp1s2', 'enp2s0', 'enp2s3']) - - -+@mock.patch( -+ "cloudinit.net.is_openvswitch_internal_interface", -+ mock.Mock(return_value=False) -+) - class TestGetIBHwaddrsByInterface(CiTestCase): - - _ib_addr = '80:00:00:28:fe:80:00:00:00:00:00:00:00:11:22:03:00:33:44:56' --- -1.8.3.1 - diff --git a/backport-testing-add-additional-mocks-to-test_net-tests-1356.patch b/backport-testing-add-additional-mocks-to-test_net-tests-1356.patch new file mode 100644 index 0000000000000000000000000000000000000000..b17be311b68472b438086dc34d5be90820847877 --- /dev/null +++ b/backport-testing-add-additional-mocks-to-test_net-tests-1356.patch @@ -0,0 +1,42 @@ +From d8f39d79fcdb548252823949a4b24f49a00e8c27 Mon Sep 17 00:00:00 2001 +From: yangzz-97 <70520104+yangzz-97@users.noreply.github.com> +Date: Thu, 31 Mar 2022 22:00:33 +0800 +Subject: [PATCH 193/195] testing: add additional mocks to test_net tests + (#1356) + +Tests in tests/unittests/test_net.py::TestGetInterfaces were missing +mocks for bond and failover calls. + +Signed-off-by: yangzz-97 +--- + tests/unittests/test_net.py | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py +index fa8b99a0..6844c329 100644 +--- a/tests/unittests/test_net.py ++++ b/tests/unittests/test_net.py +@@ -7454,6 +7454,12 @@ class TestGetInterfaces(CiTestCase): + def _se_interface_has_own_mac(self, name): + return name in self.data["own_macs"] + ++ def _se_is_bond(self, name): ++ return name in self.data["bonds"] ++ ++ def _se_is_netfailover(self, name): ++ return False ++ + def _mock_setup(self): + self.data = copy.deepcopy(self._data) + self.data["devices"] = set(list(self.data["macs"].keys())) +@@ -7465,6 +7471,8 @@ class TestGetInterfaces(CiTestCase): + "is_vlan", + "device_driver", + "device_devid", ++ "is_bond", ++ "is_netfailover", + ) + self.mocks = {} + for n in mocks: +-- +2.27.0 \ No newline at end of file diff --git a/bugfix-cloud-init-add-openEuler-os.patch b/bugfix-cloud-init-add-openEuler-os.patch index 7404035306ddb11557158c28cada67e0d4f7b7fd..b86d26c9784fd86f679ab7d6e9a7d568b8c122a0 100644 --- a/bugfix-cloud-init-add-openEuler-os.patch +++ b/bugfix-cloud-init-add-openEuler-os.patch @@ -7,105 +7,104 @@ reason: add openEuler into distros Signed-off-by: chengquan --- - .../0001-cloud-init-Update-patch-information.patch | 68 ++++++++++++++++++++++ - cloud-init-20.3/cloudinit/config/cc_ntp.py | 2 +- - cloud-init-20.3/cloudinit/config/cc_resolv_conf.py | 2 +- - cloud-init-20.3/cloudinit/config/cc_rh_subscription.py | 2 +- - cloud-init-20.3/cloudinit/config/cc_spacewalk.py | 2 +- - .../cloudinit/config/cc_yum_add_repo.py | 2 +- - cloud-init-20.3/cloudinit/distros/__init__.py | 2 +- - cloud-init-20.3/cloudinit/distros/openEuler.py | 12 ++++ - cloud-init-20.3/cloudinit/util.py | 2 +- - cloud-init-20.3/config/cloud.cfg.tmpl | 8 +-- - cloud-init-20.3/systemd/cloud-init.service.tmpl | 2 +- - cloud-init-20.3/tests/cloud_tests/util.py | 2 +- - cloud-init-20.3/tools/render-cloudcfg | 2 +- - 14 files changed, 95 insertions(+), 15 deletions(-) - create mode 100644 cloud-init-19.4/cloudinit/distros/openEuler.py + cloudinit/config/cc_ntp.py | 2 +- + cloudinit/config/cc_resolv_conf.py | 2 +- + cloudinit/config/cc_rh_subscription.py | 2 +- + cloudinit/config/cc_spacewalk.py | 2 +- + cloudinit/config/cc_yum_add_repo.py | 2 +- + cloudinit/distros/__init__.py | 2 +- + cloudinit/distros/openeuler.py | 12 ++++++++++++ + config/cloud.cfg.tmpl | 8 ++++---- + systemd/cloud-init-generator.tmpl | 2 +- + systemd/cloud-init.service.tmpl | 2 +- + tools/render-cloudcfg | 2 +- + tests/unittests/test_cli.py | 2 +- + 12 files changed, 26 insertions(+), 14 deletions(-) + create mode 100644 cloudinit/distros/openeuler.py diff --git a/cloudinit/config/cc_ntp.py b/cloudinit/config/cc_ntp.py -index 3d7279d..ae6f06b 100644 +index 25bba76..8f576f3 100644 --- a/cloudinit/config/cc_ntp.py +++ b/cloudinit/config/cc_ntp.py -@@ -25,7 +25,7 @@ frequency = PER_INSTANCE - NTP_CONF = '/etc/ntp.conf' - NR_POOL_SERVERS = 4 - distros = ['alpine', 'centos', 'debian', 'fedora', 'opensuse', 'rhel', -- 'sles', 'ubuntu'] -+ 'sles', 'ubuntu', 'openEuler'] - - NTP_CLIENT_CONFIG = { - 'chrony': { +@@ -33,7 +33,7 @@ distros = [ + "eurolinux", + "fedora", + "miraclelinux", +- "openEuler", ++ "openeuler", + "opensuse", + "photon", + "rhel", diff --git a/cloudinit/config/cc_resolv_conf.py b/cloudinit/config/cc_resolv_conf.py -index 519e66e..dc093fb 100644 +index b2970d5..d24cd3a 100644 --- a/cloudinit/config/cc_resolv_conf.py +++ b/cloudinit/config/cc_resolv_conf.py -@@ -55,7 +55,7 @@ LOG = logging.getLogger(__name__) - +@@ -54,7 +54,7 @@ LOG = logging.getLogger(__name__) + frequency = PER_INSTANCE - --distros = ['alpine', 'fedora', 'opensuse', 'rhel', 'sles'] -+distros = ['alpine', 'fedora', 'opensuse', 'rhel', 'sles', 'openEuler'] - - - def generate_resolv_conf(template_fn, params, target_fname="/etc/resolv.conf"): + +-distros = ["alpine", "fedora", "opensuse", "photon", "rhel", "sles"] ++distros = ["alpine", "fedora", "opensuse", "photon", "rhel", "sles", 'openeuler'] + + RESOLVE_CONFIG_TEMPLATE_MAP = { + "/etc/resolv.conf": "resolv.conf", diff --git a/cloudinit/config/cc_rh_subscription.py b/cloudinit/config/cc_rh_subscription.py -index 28d62e9..9a25767 100644 +index b81a7a9..74392ca 100644 --- a/cloudinit/config/cc_rh_subscription.py +++ b/cloudinit/config/cc_rh_subscription.py -@@ -44,7 +44,7 @@ from cloudinit import util - +@@ -43,7 +43,7 @@ from cloudinit import subp, util + LOG = logging.getLogger(__name__) - --distros = ['fedora', 'rhel'] -+distros = ['fedora', 'rhel', 'openEuler'] - - + +-distros = ["fedora", "rhel"] ++distros = ["fedora", "rhel", "openeuler"] + + def handle(name, cfg, _cloud, log, _args): diff --git a/cloudinit/config/cc_spacewalk.py b/cloudinit/config/cc_spacewalk.py -index 9508360..0cee8a7 100644 +index 3fa6c38..4374599 100644 --- a/cloudinit/config/cc_spacewalk.py +++ b/cloudinit/config/cc_spacewalk.py -@@ -30,7 +30,7 @@ For more information about spacewalk see: https://fedorahosted.org/spacewalk/ +@@ -29,7 +29,7 @@ For more information about spacewalk see: https://fedorahosted.org/spacewalk/ + from cloudinit import subp - - --distros = ['redhat', 'fedora'] -+distros = ['redhat', 'fedora', 'openEuler'] - required_packages = ['rhn-setup'] + +-distros = ["redhat", "fedora"] ++distros = ["redhat", "fedora", "openeuler"] + required_packages = ["rhn-setup"] def_ca_cert_path = "/usr/share/rhn/RHN-ORG-TRUSTED-SSL-CERT" - + diff --git a/cloudinit/config/cc_yum_add_repo.py b/cloudinit/config/cc_yum_add_repo.py -index 01fe683..1b7c783 100644 +index 7a23268..971e97c 100644 --- a/cloudinit/config/cc_yum_add_repo.py +++ b/cloudinit/config/cc_yum_add_repo.py -@@ -36,7 +36,7 @@ from configparser import ConfigParser - - from cloudinit import util - --distros = ['centos', 'fedora', 'rhel'] -+distros = ['centos', 'fedora', 'rhel', 'openEuler'] - - - def _canonicalize_id(repo_id): +@@ -43,7 +43,7 @@ distros = [ + "cloudlinux", + "eurolinux", + "fedora", +- "openEuler", ++ "openeuler", + "photon", + "rhel", + "rocky", diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py -index 2537608..2492962 100755 +index 76acd6a..b75bb9c 100755 --- a/cloudinit/distros/__init__.py +++ b/cloudinit/distros/__init__.py -@@ -45,7 +45,7 @@ OSFAMILIES = { - 'debian': ['debian', 'ubuntu'], - 'freebsd': ['freebsd'], - 'gentoo': ['gentoo'], -- 'redhat': ['amazon', 'centos', 'fedora', 'rhel'], -+ 'redhat': ['amazon', 'centos', 'fedora', 'rhel', 'openEuler'], - 'suse': ['opensuse', 'sles'], - } - -diff --git a/cloudinit/distros/openEuler.py b/cloudinit/distros/openEuler.py +@@ -46,7 +46,7 @@ OSFAMILIES = { + "eurolinux", + "fedora", + "miraclelinux", +- "openEuler", ++ "openeuler", + "photon", + "rhel", + "rocky", +diff --git a/cloudinit/distros/openeuler.py b/cloudinit/distros/openeuler.py new file mode 100644 index 0000000..7505ca4 --- /dev/null -+++ b/cloudinit/distros/openEuler.py ++++ b/cloudinit/distros/openeuler.py @@ -0,0 +1,12 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2019-2019. All rights reserved. +# This file is part of cloud-init. See LICENSE file for license information. @@ -119,95 +118,99 @@ index 0000000..7505ca4 + pass + +# vi: ts=4 expandtab -diff --git a/cloudinit/util.py b/cloudinit/util.py -index cf9e349..39a6c50 100644 ---- a/cloudinit/util.py -+++ b/cloudinit/util.py -@@ -549,7 +549,7 @@ def system_info(): - linux_dist = info['dist'][0].lower() - if linux_dist in ( - 'alpine', 'arch', 'centos', 'debian', 'fedora', 'rhel', -- 'suse'): -+ 'suse', 'openEuler'): - var = linux_dist - elif linux_dist in ('ubuntu', 'linuxmint', 'mint'): - var = 'ubuntu' diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl -index 2beb9b0..2318741 100644 +index fb4b456..6702801 100644 --- a/config/cloud.cfg.tmpl +++ b/config/cloud.cfg.tmpl -@@ -21,7 +21,7 @@ disable_root: false - disable_root: true +@@ -33,7 +33,7 @@ disable_root: true {% endif %} - --{% if variant in ["alpine", "amazon", "centos", "fedora", "rhel"] %} -+{% if variant in ["alpine", "amazon", "centos", "fedora", "rhel", "openEuler"] %} + + {% if variant in ["almalinux", "alpine", "amazon", "centos", "cloudlinux", "eurolinux", +- "fedora", "miraclelinux", "openEuler", "rhel", "rocky", "virtuozzo"] %} ++ "fedora", "miraclelinux", "openeuler", "rhel", "rocky", "virtuozzo"] %} mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2'] {% if variant == "amazon" %} resize_rootfs: noblock -@@ -92,7 +92,7 @@ cloud_config_modules: - - ssh-import-id +@@ -111,7 +111,7 @@ cloud_config_modules: - locale + {% endif %} - set-passwords --{% if variant in ["rhel", "fedora"] %} -+{% if variant in ["rhel", "fedora", "openEuler"] %} +-{% if variant in ["rhel", "fedora", "photon"] %} ++{% if variant in ["rhel", "fedora", "photon", "openeuler"] %} + {% if variant not in ["photon"] %} - spacewalk - - yum-add-repo {% endif %} -@@ -153,7 +153,7 @@ system_info: +@@ -177,7 +177,7 @@ cloud_final_modules: + system_info: # This will affect which distro class gets used - {% if variant in ["alpine", "amazon", "arch", "centos", "debian", - "fedora", "freebsd", "netbsd", "openbsd", "rhel", -- "suse", "ubuntu"] %} -+ "suse", "ubuntu", "openEuler"] %} + {% if variant in ["almalinux", "alpine", "amazon", "arch", "centos", "cloudlinux", "debian", +- "eurolinux", "fedora", "freebsd", "gentoo", "netbsd", "miraclelinux", "openbsd", "openEuler", ++ "eurolinux", "fedora", "freebsd", "gentoo", "netbsd", "miraclelinux", "openbsd", "openeuler", + "photon", "rhel", "rocky", "suse", "ubuntu", "virtuozzo"] %} distro: {{ variant }} - {% else %} - # Unknown/fallback distro. -@@ -205,7 +205,7 @@ system_info: + {% elif variant in ["dragonfly"] %} +@@ -232,7 +232,7 @@ system_info: security: http://ports.ubuntu.com/ubuntu-ports ssh_svcname: ssh - {% elif variant in ["alpine", "amazon", "arch", "centos", "fedora", -- "rhel", "suse"] %} -+ "rhel", "suse", "openEuler"] %} + {% elif variant in ["almalinux", "alpine", "amazon", "arch", "centos", "cloudlinux", "eurolinux", +- "fedora", "gentoo", "miraclelinux", "openEuler", "rhel", "rocky", "suse", "virtuozzo"] %} ++ "fedora", "gentoo", "miraclelinux", "openeuler", "rhel", "rocky", "suse", "virtuozzo"] %} # Default user name + that default users groups (if added/used) default_user: {% if variant == "amazon" %} diff --git a/systemd/cloud-init.service.tmpl b/systemd/cloud-init.service.tmpl -index af6d9a8..fd1babf 100644 +index e71e567..ce4f183 100644 --- a/systemd/cloud-init.service.tmpl +++ b/systemd/cloud-init.service.tmpl -@@ -10,7 +10,7 @@ After=systemd-networkd-wait-online.service - {% if variant in ["ubuntu", "unknown", "debian"] %} +@@ -13,7 +13,7 @@ After=systemd-networkd-wait-online.service After=networking.service {% endif %} --{% if variant in ["centos", "fedora", "rhel"] %} -+{% if variant in ["centos", "fedora", "rhel", "openEuler"] %} + {% if variant in ["almalinux", "centos", "cloudlinux", "eurolinux", "fedora", +- "miraclelinux", "openEuler", "rhel", "rocky", "virtuozzo"] %} ++ "miraclelinux", "openeuler", "rhel", "rocky", "virtuozzo"] %} After=network.service After=NetworkManager.service {% endif %} -diff --git a/tests/cloud_tests/util.py b/tests/cloud_tests/util.py -index 7dcccbd..87f0e3f 100644 ---- a/tests/cloud_tests/util.py -+++ b/tests/cloud_tests/util.py -@@ -23,7 +23,7 @@ from tests.cloud_tests import LOG - - OS_FAMILY_MAPPING = { - 'debian': ['debian', 'ubuntu'], -- 'redhat': ['centos', 'rhel', 'fedora'], -+ 'redhat': ['centos', 'rhel', 'fedora', 'openEuler'], - 'gentoo': ['gentoo'], - 'freebsd': ['freebsd'], - 'suse': ['sles'], diff --git a/tools/render-cloudcfg b/tools/render-cloudcfg -index ed45484..6d1fa6e 100755 +index 176df36..6e79e95 100755 --- a/tools/render-cloudcfg +++ b/tools/render-cloudcfg -@@ -6,7 +6,7 @@ import sys - - VARIANTS = ["alpine", "amazon", "arch", "centos", "debian", "fedora", - "freebsd", "netbsd", "openbsd", "rhel", "suse", "ubuntu", -- "unknown"] -+ "unknown", "openEuler"] - - - if "avoid-pep8-E402-import-not-top-of-file": +@@ -24,7 +24,7 @@ def main(): + "miraclelinux", + "netbsd", + "openbsd", +- "openEuler", ++ "openeuler", + "photon", + "rhel", + "suse", + +diff --git a/tests/unittests/test_cli.py b/tests/unittests/test_cli.py +index bed73a9..01945cc 100644 +--- a/tests/unittests/test_cli.py ++++ b/tests/unittests/test_cli.py +@@ -257,7 +257,7 @@ class TestCLI(test_helpers.FilesystemMockingTestCase): + "**Supported distros:** all", + "**Supported distros:** almalinux, alpine, centos, " + "cloudlinux, debian, eurolinux, fedora, miraclelinux, " +- "openEuler, opensuse, photon, rhel, rocky, sles, ubuntu, " ++ "openeuler, opensuse, photon, rhel, rocky, sles, ubuntu, " + "virtuozzo", + "**Config schema**:\n **resize_rootfs:** " + "(true/false/noblock)", +diff --git a/systemd/cloud-init-generator.tmpl b/systemd/cloud-init-generator.tmpl +index 74d4742..a7cf381 100644 +--- a/systemd/cloud-init-generator.tmpl ++++ b/systemd/cloud-init-generator.tmpl +@@ -84,7 +84,7 @@ default() { + check_for_datasource() { + local ds_rc="" + {% if variant in ["almalinux", "centos", "cloudlinux", "eurolinux", "fedora", +- "miraclelinux", "openEuler", "rhel", "rocky", "virtuozzo"] %} ++ "miraclelinux", "openeuler", "rhel", "rocky", "virtuozzo"] %} + local dsidentify="/usr/libexec/cloud-init/ds-identify" + {% else %} + local dsidentify="/usr/lib/cloud-init/ds-identify" +-- +1.8.3.1 + diff --git a/bugfix-sort-requirements.patch b/bugfix-sort-requirements.patch index 438fc768553e2532e74151b421857a57bfb3bdfd..dcbb03aa682b7c08c25c920e7cc882f34a43d23a 100644 --- a/bugfix-sort-requirements.patch +++ b/bugfix-sort-requirements.patch @@ -7,17 +7,20 @@ reason: sort requirements in setup Signed-off-by: chengquan --- - cloud-init-20.3/setup.py | 1 + + setup.py | 1 + 1 file changed, 1 insertion(+) -diff -Nur a/setup.py b/setup.py ---- a/setup.py 2019-04-11 20:27:41.526622810 +0800 -+++ b/setup.py 2019-04-11 20:28:21.734622815 +0800 -@@ -289,6 +289,7 @@ +diff --git a/setup.py b/setup.py +index a9132d2..a81c1e9 100755 +--- a/setup.py ++++ b/setup.py +@@ -324,6 +324,7 @@ cmdclass = { } - + requirements = read_requires() +requirements.sort() - + setuptools.setup( - name='cloud-init', + name="cloud-init", +-- +2.27.0 \ No newline at end of file diff --git a/cloud-init-20.4-Revert-ssh_util-handle-non-default-AuthorizedKeysFil.patch b/cloud-init-20.4-Revert-ssh_util-handle-non-default-AuthorizedKeysFil.patch deleted file mode 100644 index 49563272f64eb6080e5468dbbb521a837bef6ea1..0000000000000000000000000000000000000000 --- a/cloud-init-20.4-Revert-ssh_util-handle-non-default-AuthorizedKeysFil.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 9a4c22ac0b660cd2573b9a88d14a0ef39b61afca Mon Sep 17 00:00:00 2001 -From: Eduardo Otubo -Date: Wed, 3 Feb 2021 10:28:49 +0100 -Subject: [PATCH] Revert "ssh_util: handle non-default AuthorizedKeysFile - config (#586)" (#775) - -This reverts commit b0e73814db4027dba0b7dc0282e295b7f653325c. - -Signed-off-by: Eduardo Otubo ---- - cloudinit/ssh_util.py | 6 +++--- - tests/unittests/test_sshutil.py | 6 +++--- - 2 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/cloudinit/ssh_util.py b/cloudinit/ssh_util.py -index d5113996..c08042d6 100644 ---- a/cloudinit/ssh_util.py -+++ b/cloudinit/ssh_util.py -@@ -262,13 +262,13 @@ def extract_authorized_keys(username, sshd_cfg_file=DEF_SSHD_CFG): - - except (IOError, OSError): - # Give up and use a default key filename -- auth_key_fns.append(default_authorizedkeys_file) -+ auth_key_fns[0] = default_authorizedkeys_file - util.logexc(LOG, "Failed extracting 'AuthorizedKeysFile' in SSH " - "config from %r, using 'AuthorizedKeysFile' file " - "%r instead", DEF_SSHD_CFG, auth_key_fns[0]) - -- # always store all the keys in the first file configured on sshd_config -- return (auth_key_fns[0], parse_authorized_keys(auth_key_fns)) -+ # always store all the keys in the user's private file -+ return (default_authorizedkeys_file, parse_authorized_keys(auth_key_fns)) - - - def setup_user_keys(keys, username, options=None): -diff --git a/tests/unittests/test_sshutil.py b/tests/unittests/test_sshutil.py -index 88a111e3..fd1d1bac 100644 ---- a/tests/unittests/test_sshutil.py -+++ b/tests/unittests/test_sshutil.py -@@ -593,7 +593,7 @@ class TestMultipleSshAuthorizedKeysFile(test_helpers.CiTestCase): - fpw.pw_name, sshd_config) - content = ssh_util.update_authorized_keys(auth_key_entries, []) - -- self.assertEqual(authorized_keys, auth_key_fn) -+ self.assertEqual("%s/.ssh/authorized_keys" % fpw.pw_dir, auth_key_fn) - self.assertTrue(VALID_CONTENT['rsa'] in content) - self.assertTrue(VALID_CONTENT['dsa'] in content) - -@@ -610,7 +610,7 @@ class TestMultipleSshAuthorizedKeysFile(test_helpers.CiTestCase): - sshd_config = self.tmp_path('sshd_config') - util.write_file( - sshd_config, -- "AuthorizedKeysFile %s %s" % (user_keys, authorized_keys) -+ "AuthorizedKeysFile %s %s" % (authorized_keys, user_keys) - ) - - (auth_key_fn, auth_key_entries) = ssh_util.extract_authorized_keys( -@@ -618,7 +618,7 @@ class TestMultipleSshAuthorizedKeysFile(test_helpers.CiTestCase): - ) - content = ssh_util.update_authorized_keys(auth_key_entries, []) - -- self.assertEqual(user_keys, auth_key_fn) -+ self.assertEqual("%s/.ssh/authorized_keys" % fpw.pw_dir, auth_key_fn) - self.assertTrue(VALID_CONTENT['rsa'] in content) - self.assertTrue(VALID_CONTENT['dsa'] in content) - --- -2.27.0 - diff --git a/cloud-init-20.4-disable-lxd-tests.patch b/cloud-init-20.4-disable-lxd-tests.patch deleted file mode 100644 index 4a070634262cbbb6c836cccdadbad2f2a4db7422..0000000000000000000000000000000000000000 --- a/cloud-init-20.4-disable-lxd-tests.patch +++ /dev/null @@ -1,33 +0,0 @@ -From f70a9a0a98c0af5a7b2aea9a8e4b40bbe1668038 Mon Sep 17 00:00:00 2001 -From: Eduardo Otubo -Date: Thu, 3 Dec 2020 12:31:42 +0100 -Subject: [PATCH 1/3] Disable LXD tests - -Signed-off-by: Eduardo Otubo ---- - tests/cloud_tests/platforms/__init__.py | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/tests/cloud_tests/platforms/__init__.py b/tests/cloud_tests/platforms/__init__.py -index e506baa0..e7efcba5 100644 ---- a/tests/cloud_tests/platforms/__init__.py -+++ b/tests/cloud_tests/platforms/__init__.py -@@ -3,7 +3,6 @@ - """Main init.""" - - from .ec2 import platform as ec2 --from .lxd import platform as lxd - from .nocloudkvm import platform as nocloudkvm - from .azurecloud import platform as azurecloud - from ..util import emit_dots_on_travis -@@ -11,7 +10,6 @@ from ..util import emit_dots_on_travis - PLATFORMS = { - 'ec2': ec2.EC2Platform, - 'nocloud-kvm': nocloudkvm.NoCloudKVMPlatform, -- 'lxd': lxd.LXDPlatform, - 'azurecloud': azurecloud.AzureCloudPlatform, - } - --- -2.27.0 - diff --git a/cloud-init-20.4-nm-controlled.patch b/cloud-init-20.4-nm-controlled.patch index 606e7bc3801328bb4b6cc2e0d901cc7f9d26d39d..c42ffc0d907ec1ee2d1855de7fc20c5a7d26061c 100644 --- a/cloud-init-20.4-nm-controlled.patch +++ b/cloud-init-20.4-nm-controlled.patch @@ -19,10 +19,10 @@ Signed-off-by: Ryan McCabe 3 files changed, 1 insertion(+), 58 deletions(-) diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py -index a930e612..9c822c3e 100644 +index ef4543b..13c6ad7 100644 --- a/cloudinit/net/sysconfig.py +++ b/cloudinit/net/sysconfig.py -@@ -289,7 +289,7 @@ class Renderer(renderer.Renderer): +@@ -290,7 +290,7 @@ class Renderer(renderer.Renderer): # details about this) iface_defaults = { @@ -32,10 +32,10 @@ index a930e612..9c822c3e 100644 'suse': {'BOOTPROTO': 'static', 'STARTMODE': 'auto'}, } diff --git a/tests/unittests/test_distros/test_netconfig.py b/tests/unittests/test_distros/test_netconfig.py -index a1df066a..bc167f94 100644 +index d09e46a..3f01c99 100644 --- a/tests/unittests/test_distros/test_netconfig.py +++ b/tests/unittests/test_distros/test_netconfig.py -@@ -484,7 +484,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): +@@ -503,7 +503,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): GATEWAY=192.168.1.254 IPADDR=192.168.1.5 NETMASK=255.255.255.0 @@ -43,7 +43,7 @@ index a1df066a..bc167f94 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -492,7 +491,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): +@@ -511,7 +510,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): self.ifcfg_path('eth1'): dedent("""\ BOOTPROTO=dhcp DEVICE=eth1 @@ -51,7 +51,7 @@ index a1df066a..bc167f94 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -517,7 +515,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): +@@ -536,7 +534,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): IPV6_AUTOCONF=no IPV6_DEFAULTGW=2607:f0d0:1002:0011::1 IPV6_FORCE_ACCEPT_RA=no @@ -59,7 +59,7 @@ index a1df066a..bc167f94 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -525,7 +522,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): +@@ -544,7 +541,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): self.ifcfg_path('eth1'): dedent("""\ BOOTPROTO=dhcp DEVICE=eth1 @@ -67,7 +67,7 @@ index a1df066a..bc167f94 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -559,7 +555,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): +@@ -578,7 +574,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): HWADDR=00:16:3e:60:7c:df IPADDR=192.10.1.2 NETMASK=255.255.255.0 @@ -75,7 +75,7 @@ index a1df066a..bc167f94 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -569,7 +564,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): +@@ -588,7 +583,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): DEVICE=infra0 IPADDR=10.0.1.2 NETMASK=255.255.0.0 @@ -83,7 +83,7 @@ index a1df066a..bc167f94 100644 ONBOOT=yes PHYSDEV=eth0 USERCTL=no -@@ -598,7 +592,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): +@@ -617,7 +611,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): DEVICE=eth0 IPADDR=192.10.1.2 NETMASK=255.255.255.0 @@ -91,7 +91,7 @@ index a1df066a..bc167f94 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -608,7 +601,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): +@@ -627,7 +620,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): DEVICE=eth0.1001 IPADDR=10.0.1.2 NETMASK=255.255.0.0 @@ -100,7 +100,7 @@ index a1df066a..bc167f94 100644 PHYSDEV=eth0 USERCTL=no diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py -index 70453683..47a71964 100644 +index 094450b..6294f4b 100644 --- a/tests/unittests/test_net.py +++ b/tests/unittests/test_net.py @@ -535,7 +535,6 @@ GATEWAY=172.19.3.254 @@ -127,7 +127,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -884,7 +881,6 @@ NETWORK_CONFIGS = { +@@ -910,7 +907,6 @@ NETWORK_CONFIGS = { BOOTPROTO=none DEVICE=eth1 HWADDR=cf:d6:af:48:e8:80 @@ -135,7 +135,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no"""), -@@ -901,7 +897,6 @@ NETWORK_CONFIGS = { +@@ -927,7 +923,6 @@ NETWORK_CONFIGS = { IPADDR=192.168.21.3 NETMASK=255.255.255.0 METRIC=10000 @@ -143,7 +143,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no"""), -@@ -1032,7 +1027,6 @@ NETWORK_CONFIGS = { +@@ -1075,7 +1070,6 @@ NETWORK_CONFIGS = { IPV6_AUTOCONF=no IPV6_FORCE_ACCEPT_RA=no NETMASK=255.255.255.0 @@ -151,7 +151,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -1095,7 +1089,6 @@ NETWORK_CONFIGS = { +@@ -1144,7 +1138,6 @@ NETWORK_CONFIGS = { DHCPV6C=yes IPV6INIT=yes DEVICE=iface0 @@ -159,7 +159,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -1150,7 +1143,6 @@ NETWORK_CONFIGS = { +@@ -1199,7 +1192,6 @@ NETWORK_CONFIGS = { IPV6INIT=yes IPV6_FORCE_ACCEPT_RA=yes DEVICE=iface0 @@ -167,7 +167,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -1205,7 +1197,6 @@ NETWORK_CONFIGS = { +@@ -1261,7 +1253,6 @@ NETWORK_CONFIGS = { IPV6INIT=yes IPV6_FORCE_ACCEPT_RA=no DEVICE=iface0 @@ -175,7 +175,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -1250,7 +1241,6 @@ NETWORK_CONFIGS = { +@@ -1313,7 +1304,6 @@ NETWORK_CONFIGS = { IPV6_AUTOCONF=yes IPV6INIT=yes DEVICE=iface0 @@ -183,7 +183,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -1277,7 +1267,6 @@ NETWORK_CONFIGS = { +@@ -1340,7 +1330,6 @@ NETWORK_CONFIGS = { IPV6_AUTOCONF=no IPV6_FORCE_ACCEPT_RA=no DEVICE=iface0 @@ -191,7 +191,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -1324,7 +1313,6 @@ NETWORK_CONFIGS = { +@@ -1387,7 +1376,6 @@ NETWORK_CONFIGS = { IPV6_AUTOCONF=yes IPV6INIT=yes DEVICE=iface0 @@ -199,15 +199,15 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -1371,7 +1359,6 @@ NETWORK_CONFIGS = { - IPV6INIT=yes +@@ -1435,7 +1423,6 @@ NETWORK_CONFIGS = { + IPV6_AUTOCONF=no IPV6_FORCE_ACCEPT_RA=yes DEVICE=iface0 - NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -1404,7 +1391,6 @@ NETWORK_CONFIGS = { +@@ -1468,7 +1455,6 @@ NETWORK_CONFIGS = { 'ifcfg-iface0': textwrap.dedent("""\ BOOTPROTO=dhcp DEVICE=iface0 @@ -215,7 +215,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -1447,7 +1433,6 @@ NETWORK_CONFIGS = { +@@ -1511,7 +1497,6 @@ NETWORK_CONFIGS = { BOOTPROTO=dhcp DEVICE=iface0 ETHTOOL_OPTS="wol g" @@ -223,7 +223,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -1736,7 +1721,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -1800,7 +1785,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true DHCPV6C=yes IPV6INIT=yes MACADDR=aa:bb:cc:dd:ee:ff @@ -231,7 +231,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Bond USERCTL=no"""), -@@ -1744,7 +1728,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -1808,7 +1792,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true BOOTPROTO=dhcp DEVICE=bond0.200 DHCLIENT_SET_DEFAULT_ROUTE=no @@ -239,7 +239,7 @@ index 70453683..47a71964 100644 ONBOOT=yes PHYSDEV=bond0 USERCTL=no -@@ -1762,7 +1745,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -1826,7 +1809,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true IPV6_DEFAULTGW=2001:4800:78ff:1b::1 MACADDR=bb:bb:bb:bb:bb:aa NETMASK=255.255.255.0 @@ -247,7 +247,7 @@ index 70453683..47a71964 100644 ONBOOT=yes PRIO=22 STP=no -@@ -1772,7 +1754,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -1836,7 +1818,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true BOOTPROTO=none DEVICE=eth0 HWADDR=c0:d6:9f:2c:e8:80 @@ -255,7 +255,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no"""), -@@ -1789,7 +1770,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -1853,7 +1834,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true MTU=1500 NETMASK=255.255.255.0 NETMASK1=255.255.255.0 @@ -263,7 +263,7 @@ index 70453683..47a71964 100644 ONBOOT=yes PHYSDEV=eth0 USERCTL=no -@@ -1799,7 +1779,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -1863,7 +1843,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true DEVICE=eth1 HWADDR=aa:d6:9f:2c:e8:80 MASTER=bond0 @@ -271,7 +271,7 @@ index 70453683..47a71964 100644 ONBOOT=yes SLAVE=yes TYPE=Ethernet -@@ -1809,7 +1788,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -1873,7 +1852,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true DEVICE=eth2 HWADDR=c0:bb:9f:2c:e8:80 MASTER=bond0 @@ -279,7 +279,7 @@ index 70453683..47a71964 100644 ONBOOT=yes SLAVE=yes TYPE=Ethernet -@@ -1819,7 +1797,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -1883,7 +1861,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true BRIDGE=br0 DEVICE=eth3 HWADDR=66:bb:9f:2c:e8:80 @@ -287,7 +287,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no"""), -@@ -1828,7 +1805,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -1892,7 +1869,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true BRIDGE=br0 DEVICE=eth4 HWADDR=98:bb:9f:2c:e8:80 @@ -295,7 +295,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no"""), -@@ -1837,7 +1813,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -1901,7 +1877,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true DEVICE=eth5 DHCLIENT_SET_DEFAULT_ROUTE=no HWADDR=98:bb:9f:2c:e8:8a @@ -303,7 +303,7 @@ index 70453683..47a71964 100644 ONBOOT=no TYPE=Ethernet USERCTL=no"""), -@@ -1848,7 +1823,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -1912,7 +1887,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true IPADDR=192.168.200.7 MTU=9000 NETMASK=255.255.255.0 @@ -311,7 +311,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=InfiniBand USERCTL=no"""), -@@ -2293,7 +2267,6 @@ iface bond0 inet6 static +@@ -2357,7 +2331,6 @@ iface bond0 inet6 static MTU=9000 NETMASK=255.255.255.0 NETMASK1=255.255.255.0 @@ -319,7 +319,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Bond USERCTL=no -@@ -2303,7 +2276,6 @@ iface bond0 inet6 static +@@ -2367,7 +2340,6 @@ iface bond0 inet6 static DEVICE=bond0s0 HWADDR=aa:bb:cc:dd:e8:00 MASTER=bond0 @@ -327,7 +327,7 @@ index 70453683..47a71964 100644 ONBOOT=yes SLAVE=yes TYPE=Ethernet -@@ -2325,7 +2297,6 @@ iface bond0 inet6 static +@@ -2389,7 +2361,6 @@ iface bond0 inet6 static DEVICE=bond0s1 HWADDR=aa:bb:cc:dd:e8:01 MASTER=bond0 @@ -335,7 +335,7 @@ index 70453683..47a71964 100644 ONBOOT=yes SLAVE=yes TYPE=Ethernet -@@ -2382,7 +2353,6 @@ iface bond0 inet6 static +@@ -2446,7 +2417,6 @@ iface bond0 inet6 static BOOTPROTO=none DEVICE=en0 HWADDR=aa:bb:cc:dd:e8:00 @@ -343,7 +343,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no"""), -@@ -2401,7 +2371,6 @@ iface bond0 inet6 static +@@ -2465,7 +2435,6 @@ iface bond0 inet6 static MTU=2222 NETMASK=255.255.255.0 NETMASK1=255.255.255.0 @@ -351,7 +351,7 @@ index 70453683..47a71964 100644 ONBOOT=yes PHYSDEV=en0 USERCTL=no -@@ -2466,7 +2435,6 @@ iface bond0 inet6 static +@@ -2530,7 +2499,6 @@ iface bond0 inet6 static DEVICE=br0 IPADDR=192.168.2.2 NETMASK=255.255.255.0 @@ -359,7 +359,7 @@ index 70453683..47a71964 100644 ONBOOT=yes PRIO=22 STP=no -@@ -2482,7 +2450,6 @@ iface bond0 inet6 static +@@ -2546,7 +2514,6 @@ iface bond0 inet6 static IPV6INIT=yes IPV6_AUTOCONF=no IPV6_FORCE_ACCEPT_RA=no @@ -367,7 +367,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -2496,7 +2463,6 @@ iface bond0 inet6 static +@@ -2560,7 +2527,6 @@ iface bond0 inet6 static IPV6INIT=yes IPV6_AUTOCONF=no IPV6_FORCE_ACCEPT_RA=no @@ -375,7 +375,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -2590,7 +2556,6 @@ iface bond0 inet6 static +@@ -2654,7 +2620,6 @@ iface bond0 inet6 static HWADDR=52:54:00:12:34:00 IPADDR=192.168.1.2 NETMASK=255.255.255.0 @@ -383,7 +383,7 @@ index 70453683..47a71964 100644 ONBOOT=no TYPE=Ethernet USERCTL=no -@@ -2600,7 +2565,6 @@ iface bond0 inet6 static +@@ -2664,7 +2629,6 @@ iface bond0 inet6 static DEVICE=eth1 HWADDR=52:54:00:12:34:aa MTU=1480 @@ -391,7 +391,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -2609,7 +2573,6 @@ iface bond0 inet6 static +@@ -2673,7 +2637,6 @@ iface bond0 inet6 static BOOTPROTO=none DEVICE=eth2 HWADDR=52:54:00:12:34:ff @@ -399,7 +399,7 @@ index 70453683..47a71964 100644 ONBOOT=no TYPE=Ethernet USERCTL=no -@@ -3026,7 +2989,6 @@ class TestRhelSysConfigRendering(CiTestCase): +@@ -3094,7 +3057,6 @@ class TestRhelSysConfigRendering(CiTestCase): BOOTPROTO=dhcp DEVICE=eth1000 HWADDR=07-1c-c6-75-a4-be @@ -407,7 +407,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -3147,7 +3109,6 @@ GATEWAY=10.0.2.2 +@@ -3215,7 +3177,6 @@ GATEWAY=10.0.2.2 HWADDR=52:54:00:12:34:00 IPADDR=10.0.2.15 NETMASK=255.255.255.0 @@ -415,7 +415,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -3178,7 +3139,6 @@ HWADDR=fa:16:3e:25:b4:59 +@@ -3246,7 +3207,6 @@ HWADDR=fa:16:3e:25:b4:59 IPADDR=51.68.89.122 MTU=1500 NETMASK=255.255.240.0 @@ -423,7 +423,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -3192,7 +3152,6 @@ DEVICE=eth1 +@@ -3260,7 +3220,6 @@ DEVICE=eth1 DHCLIENT_SET_DEFAULT_ROUTE=no HWADDR=fa:16:3e:b1:ca:29 MTU=9000 @@ -431,7 +431,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -3217,7 +3176,6 @@ USERCTL=no +@@ -3285,7 +3244,6 @@ USERCTL=no # BOOTPROTO=dhcp DEVICE=eth0 @@ -439,7 +439,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -3492,7 +3450,6 @@ USERCTL=no +@@ -3560,7 +3518,6 @@ USERCTL=no IPV6_FORCE_ACCEPT_RA=no IPV6_DEFAULTGW=2001:db8::1 NETMASK=255.255.255.0 @@ -447,7 +447,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -3517,7 +3474,6 @@ USERCTL=no +@@ -3585,7 +3542,6 @@ USERCTL=no 'ifcfg-eno1': textwrap.dedent("""\ BOOTPROTO=none DEVICE=eno1 @@ -455,7 +455,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -3528,7 +3484,6 @@ USERCTL=no +@@ -3596,7 +3552,6 @@ USERCTL=no IPADDR=192.6.1.9 MTU=1495 NETMASK=255.255.255.0 @@ -463,7 +463,7 @@ index 70453683..47a71964 100644 ONBOOT=yes PHYSDEV=eno1 USERCTL=no -@@ -3558,7 +3513,6 @@ USERCTL=no +@@ -3626,7 +3581,6 @@ USERCTL=no IPADDR=10.101.8.65 MTU=1334 NETMASK=255.255.255.192 @@ -471,7 +471,7 @@ index 70453683..47a71964 100644 ONBOOT=yes TYPE=Bond USERCTL=no -@@ -3568,7 +3522,6 @@ USERCTL=no +@@ -3636,7 +3590,6 @@ USERCTL=no BOOTPROTO=none DEVICE=enp0s0 MASTER=bond0 @@ -479,7 +479,7 @@ index 70453683..47a71964 100644 ONBOOT=yes SLAVE=yes TYPE=Bond -@@ -3579,7 +3532,6 @@ USERCTL=no +@@ -3647,7 +3600,6 @@ USERCTL=no BOOTPROTO=none DEVICE=enp0s1 MASTER=bond0 @@ -487,7 +487,7 @@ index 70453683..47a71964 100644 ONBOOT=yes SLAVE=yes TYPE=Bond -@@ -3603,7 +3555,6 @@ USERCTL=no +@@ -3671,7 +3623,6 @@ USERCTL=no DEVICE=eno1 HWADDR=07-1c-c6-75-a4-be METRIC=100 @@ -496,5 +496,5 @@ index 70453683..47a71964 100644 TYPE=Ethernet USERCTL=no -- -2.27.0 +1.8.3.1 diff --git a/cloud-init-20.4-sandbox-ca_certs-tests-to-avoid-failure.patch b/cloud-init-20.4-sandbox-ca_certs-tests-to-avoid-failure.patch deleted file mode 100644 index 20f27e330c232033f78283f925cefb0ca30c928b..0000000000000000000000000000000000000000 --- a/cloud-init-20.4-sandbox-ca_certs-tests-to-avoid-failure.patch +++ /dev/null @@ -1,46 +0,0 @@ -From f16b18607444cb41e263edfa7fb0c97ba1f7e518 Mon Sep 17 00:00:00 2001 -From: Eduardo Otubo -Date: Fri, 4 Dec 2020 11:05:08 +0100 -Subject: [PATCH] Sandbox ca_certs tests to avoid failure - -Signed-off-by: Eduardo Otubo ---- - .../unittests/test_handler/test_handler_ca_certs.py | 12 ++++-------- - 1 file changed, 4 insertions(+), 8 deletions(-) - -diff --git a/tests/unittests/test_handler/test_handler_ca_certs.py b/tests/unittests/test_handler/test_handler_ca_certs.py -index e74a0a08..a16430d5 100644 ---- a/tests/unittests/test_handler/test_handler_ca_certs.py -+++ b/tests/unittests/test_handler/test_handler_ca_certs.py -@@ -152,6 +152,7 @@ class TestAddCaCerts(TestCase): - self.paths = helpers.Paths({ - 'cloud_dir': tmpdir, - }) -+ self.add_patch("cloudinit.config.cc_ca_certs.os.stat", "m_stat") - - def test_no_certs_in_list(self): - """Test that no certificate are written if not provided.""" -@@ -215,17 +216,12 @@ class TestAddCaCerts(TestCase): - - expected = "cloud-init-ca-certs.crt\n" - -- with ExitStack() as mocks: -- mock_write = mocks.enter_context( -- mock.patch.object(util, 'write_file', autospec=True)) -- mock_stat = mocks.enter_context( -- mock.patch("cloudinit.config.cc_ca_certs.os.stat") -- ) -- mock_stat.return_value.st_size = 0 -+ with mock.patch.object(util, 'write_file', autospec=True) as m_write: -+ self.m_stat.return_value.st_size = 0 - - cc_ca_certs.add_ca_certs([cert]) - -- mock_write.assert_has_calls([ -+ m_write.assert_has_calls([ - mock.call("/usr/share/ca-certificates/cloud-init-ca-certs.crt", - cert, mode=0o644), - mock.call("/etc/ca-certificates.conf", expected, omode="wb")]) --- -2.27.0 - diff --git a/cloud-init-20.4.tar.gz b/cloud-init-20.4.tar.gz deleted file mode 100644 index 550eb04509c107f2a1dab389bc79bb348f14b231..0000000000000000000000000000000000000000 Binary files a/cloud-init-20.4.tar.gz and /dev/null differ diff --git a/cloud-init-22.1-no-override-default-network.patch b/cloud-init-22.1-no-override-default-network.patch new file mode 100644 index 0000000000000000000000000000000000000000..f869ca06581208acb38026e42ad884006bc0b827 --- /dev/null +++ b/cloud-init-22.1-no-override-default-network.patch @@ -0,0 +1,35 @@ +From 5514d5922cbc92278868bfea587c4207619d81fc Mon Sep 17 00:00:00 2001 +From: Eduardo Otubo +Date: Thu, 3 Dec 2020 12:34:01 +0100 +Subject: [PATCH 3/3] Don't override default network configuration + +Signed-off-by: Eduardo Otubo +--- + cloudinit/net/sysconfig.py | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py +index ba85c4f..90a4eb9 100644 +--- a/cloudinit/net/sysconfig.py ++++ b/cloudinit/net/sysconfig.py +@@ -1039,7 +1039,17 @@ class Renderer(renderer.Renderer): + # Distros configuring /etc/sysconfig/network as a file e.g. Centos + if sysconfig_path.endswith("network"): + util.ensure_dir(os.path.dirname(sysconfig_path)) +- netcfg = [_make_header(), "NETWORKING=yes"] ++ # Make sure that existing lines, other than overriding ones, remain ++ netcfg = [] ++ for line in util.load_file(sysconfig_path, quiet=True).split('\n'): ++ if 'cloud-init' in line: ++ break ++ if not line.startswith(('NETWORKING=', ++ 'IPV6_AUTOCONF=', ++ 'NETWORKING_IPV6=')): ++ netcfg.append(line) ++ # Now generate the cloud-init portion of sysconfig/network ++ netcfg.extend([_make_header(), 'NETWORKING=yes']) + if network_state.use_ipv6: + netcfg.append("NETWORKING_IPV6=yes") + netcfg.append("IPV6_AUTOCONF=no") +-- +2.27.0 \ No newline at end of file diff --git a/cloud-init-22.1.tar.gz b/cloud-init-22.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..a49e0b2af13ba2cd96d43267042102cc6787d331 Binary files /dev/null and b/cloud-init-22.1.tar.gz differ diff --git a/cloud-init.spec b/cloud-init.spec index 1d4c82da26d22ac77bd31eef3b06391c21d87423..8327626e17cbd0f9f6e754aa907afb4eb652b607 100644 --- a/cloud-init.spec +++ b/cloud-init.spec @@ -1,6 +1,6 @@ Name: cloud-init -Version: 20.4 -Release: 3 +Version: 22.1 +Release: 1 Summary: the defacto multi-distribution package that handles early initialization of a cloud instance. License: ASL 2.0 or GPLv3 URL: http://launchpad.net/cloud-init @@ -8,25 +8,21 @@ Source0: https://launchpad.net/%{name}/trunk/%{version}/+download/%{name}-%{vers Source1: cloud-init-tmpfiles.conf -Patch0: cloud-init-20.4-disable-lxd-tests.patch -Patch1: cloud-init-20.4-nm-controlled.patch -Patch2: cloud-init-20.4-no-override-default-network.patch -Patch3: bugfix-cloud-init-add-openEuler-os.patch -Patch4: bugfix-sort-requirements.patch -Patch5: add-variable-to-forbid-tmp-dir.patch -Patch6: cloud-init-20.4-sandbox-ca_certs-tests-to-avoid-failure.patch -Patch7: cloud-init-20.4-Revert-ssh_util-handle-non-default-AuthorizedKeysFil.patch -Patch8: backport-net-exclude-OVS-internal-interfaces-in-get_interface.patch -Patch9: backport-CVE-2021-3429-write-passwords-only-to-serial-console-lock-down-clo.patch +Patch0: cloud-init-22.1-no-override-default-network.patch +Patch1: bugfix-cloud-init-add-openEuler-os.patch +Patch2: bugfix-sort-requirements.patch +Patch3: add-variable-to-forbid-tmp-dir.patch +Patch4: backport-add-Requires-cloud-init-hotplugd.socket-in-cloud-init-hotplugd.service-file.patch +Patch5: backport-testing-add-additional-mocks-to-test_net-tests-1356.patch Patch9000: Fix-the-error-level-logs-displayed-for-the-cloud-init-local-service.patch BuildRequires: pkgconfig(systemd) python3-devel python3-setuptools systemd BuildRequires: iproute python3-configobj python3-httpretty >= 0.8.14-2 BuildRequires: python3-jinja2 python3-jsonpatch python3-jsonschema -BuildRequires: python3-mock python3-nose python3-oauthlib python3-prettytable +BuildRequires: python3-mock python3-oauthlib python3-prettytable BuildRequires: python3-pyserial python3-PyYAML python3-requests python3-six -BuildRequires: python3-unittest2 dnf %{_vendor}-release python3-pytest passwd +BuildRequires: python3-unittest2 dnf %{_vendor}-release python3-pytest passwd python3-netifaces Requires: e2fsprogs iproute python3-libselinux net-tools python3-policycoreutils Requires: procps python3-configobj python3-jinja2 python3-jsonpatch xfsprogs @@ -54,7 +50,7 @@ sed -i 's/\/etc\/redhat-release/\/etc\/%{_vendor}-release/g' setup.py %install %py3_install -- --init-system=systemd -python3 tools/render-cloudcfg --variant openEuler > %{buildroot}/%{_sysconfdir}/cloud/cloud.cfg +python3 tools/render-cloudcfg --variant openeuler > %{buildroot}/%{_sysconfdir}/cloud/cloud.cfg install -d %{buildroot}/var/lib/cloud install -d %{buildroot}/run/%{name} install -D -m 0644 %{SOURCE1} %{buildroot}/%{_tmpfilesdir}/%{name}.conf @@ -110,6 +106,9 @@ fi %{_unitdir}/cloud-config.target %{_unitdir}/cloud-init.target /usr/lib/systemd/system-generators/cloud-init-generator +%{_sysconfdir}/systemd/system/sshd-keygen@.service.d/disable-sshd-keygen-if-cloud-init-active.conf +/usr/lib/systemd/system/cloud-init-hotplugd.service +/usr/lib/systemd/system/cloud-init-hotplugd.socket %{_tmpfilesdir}/%{name}.conf %{_libexecdir}/%{name} %{_bindir}/cloud-init* @@ -126,6 +125,14 @@ fi %exclude /usr/share/doc/* %changelog +* Sat Apr 2 2022 yangzhuangzhuang - 22.1-1 +- Type:update +- ID:NA +- SUG:NA +- DESC:update to 22.1 + fix test_net.py testcase fail + add Reauires cloud-init-hotplugd.socket in cloud-init-hotplugd.service file + * Wed Sep 22 2021 yangzhuangzhuang - 20.4-3 - Type:CVE - ID:CVE-2021-3429