From 5d7981bee553a9092faa80c40feeec1cb93093f6 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Thu, 21 Sep 2023 18:10:28 +0000 Subject: [PATCH] import CS cloud-init-23.1.1-11.el9 --- .cloud-init.metadata | 2 +- .gitignore | 2 +- SOURCES/0001-Add-initial-redhat-changes.patch | 648 +--------- ...CONTROLLED-no-in-generated-interface.patch | 72 +- ...v-to-the-default-mount-configuration.patch | 42 - ...utoconnect-priority-for-network-scr.patch} | 15 +- ...4-limit-permissions-on-def_log_file.patch} | 32 +- ...e-Network-Manager-and-Netplan-as-def.patch | 92 ++ ...-native-NetworkManager-support-1224.patch} | 1074 ++-------------- ...emove-ssh_genkeytypes-in-settings.py.patch | 65 - ...revious-hostname-file-ends-with-a-ne.patch | 54 + ...-permissions-of-netrules-target-2076.patch | 121 ++ ...-data-sensitive-and-remove-log-permi.patch | 295 +++++ ...dsa-and-ed25519-key-types-when-crypt.patch | 206 +++ ...vert-Use-Network-Manager-and-Netplan.patch | 93 ++ ...-native-NetworkManager-support-1224.patch} | 1110 ++--------------- ...-not-use-the-highest-autoconnect-pri.patch | 33 + ...ysconfig-cosmetic-fix-tox-formatting.patch | 43 + ...-stateful-dhcp-config-at-par-with-sy.patch | 49 + ...add-a-method-for-ipv6-static-IP-conf.patch | 31 + ...able-sysconfig-renderer-if-network-m.patch | 62 + ...Set-higher-autoconnect-priority-for-.patch | 401 ++++++ ...renderer-as-sysconfig-for-c9s-RHEL-9.patch | 42 + ...lt-renderer-as-sysconfig-for-c9s-RHE.patch | 25 + ...erer-as-sysconfig-for-centos-rhel-41.patch | 35 + ...e-tests-to-reflect-AUTOCONNECT_PRIOR.patch | 509 ++++++++ ...s-remove-NM_CONTROLLED-no-from-tests.patch | 283 +++++ ...rt-limit-permissions-on-def_log_file.patch | 58 + ...es-to-apply-RHEL-specific-config-set.patch | 43 + ...E-based-distros-for-ca-handling-2036.patch | 90 ++ ...istent-ca-cert-config-situation-2073.patch | 85 ++ ...rent-file-mode-of-log-file-if-its-st.patch | 172 +++ ...S-VMware-modify-a-few-log-level-4284.patch | 62 + ...default-IPv6-addr-gen-mode-for-all-i.patch | 283 +++++ ...rhel-custom-files-with-upstream-1431.patch | 256 ---- ...-to-resize-encrypted-partitions-1316.patch | 516 -------- ...eady-before-cloud-init-service-runs-.patch | 36 - ...ci-Honor-system-locale-for-RHEL-1355.patch | 135 -- SOURCES/ci-Remove-rhel-specific-files.patch | 370 ------ ...tting-highest-autoconnect-priority-f.patch | 37 - ...ighest-autoconnect-priority-for-netw.patch | 37 - ...rk-Manager-and-Netplan-as-default-re.patch | 75 -- ...t-EC2-tags-in-instance-metadata-1309.patch | 165 --- ...ger-and-Netplan-as-default-renderers.patch | 109 -- ...do-not-write-localhost-when-no-hostn.patch | 801 ------------ ...ignore-var-lib-cloud-data-set-hostna.patch | 77 -- ...ake-sure-centos-settings-are-identic.patch | 139 --- ...-adjust-udev-rules-default-path-1513.patch | 57 - SPECS/cloud-init.spec | 176 ++- 49 files changed, 3590 insertions(+), 5625 deletions(-) delete mode 100644 SOURCES/0003-Adding-_netdev-to-the-default-mount-configuration.patch rename SOURCES/{0004-Setting-highest-autoconnect-priority-for-network-scr.patch => 0003-Setting-highest-autoconnect-priority-for-network-scr.patch} (80%) rename SOURCES/{0005-limit-permissions-on-def_log_file.patch => 0004-limit-permissions-on-def_log_file.patch} (75%) create mode 100644 SOURCES/0005-Manual-revert-Use-Network-Manager-and-Netplan-as-def.patch rename SOURCES/{ci-Revert-Add-native-NetworkManager-support-1224.patch => 0006-Revert-Add-native-NetworkManager-support-1224.patch} (60%) delete mode 100644 SOURCES/0006-rhel-cloud.cfg-remove-ssh_genkeytypes-in-settings.py.patch create mode 100644 SOURCES/0007-rhel-make-sure-previous-hostname-file-ends-with-a-ne.patch create mode 100644 SOURCES/0008-Don-t-change-permissions-of-netrules-target-2076.patch create mode 100644 SOURCES/0009-Make-user-vendor-data-sensitive-and-remove-log-permi.patch create mode 100644 SOURCES/0010-Do-not-generate-dsa-and-ed25519-key-types-when-crypt.patch create mode 100644 SOURCES/0011-Revert-Manual-revert-Use-Network-Manager-and-Netplan.patch rename SOURCES/{ci-Add-native-NetworkManager-support-1224.patch => 0012-Revert-Revert-Add-native-NetworkManager-support-1224.patch} (58%) create mode 100644 SOURCES/0013-net-sysconfig-do-not-use-the-highest-autoconnect-pri.patch create mode 100644 SOURCES/0014-net-sysconfig-cosmetic-fix-tox-formatting.patch create mode 100644 SOURCES/0015-nm-generate-ipv6-stateful-dhcp-config-at-par-with-sy.patch create mode 100644 SOURCES/0016-network_manager-add-a-method-for-ipv6-static-IP-conf.patch create mode 100644 SOURCES/0017-net-sysconfig-enable-sysconfig-renderer-if-network-m.patch create mode 100644 SOURCES/0018-network-manager-Set-higher-autoconnect-priority-for-.patch create mode 100644 SOURCES/0019-Set-default-renderer-as-sysconfig-for-c9s-RHEL-9.patch create mode 100644 SOURCES/0020-Revert-Set-default-renderer-as-sysconfig-for-c9s-RHE.patch create mode 100644 SOURCES/0021-Set-default-renderer-as-sysconfig-for-centos-rhel-41.patch create mode 100644 SOURCES/0022-test-fixes-update-tests-to-reflect-AUTOCONNECT_PRIOR.patch create mode 100644 SOURCES/0023-test-fixes-remove-NM_CONTROLLED-no-from-tests.patch create mode 100644 SOURCES/0024-Revert-limit-permissions-on-def_log_file.patch create mode 100644 SOURCES/0025-test-fixes-changes-to-apply-RHEL-specific-config-set.patch create mode 100644 SOURCES/0026-Enable-SUSE-based-distros-for-ca-handling-2036.patch create mode 100644 SOURCES/0027-Handle-non-existent-ca-cert-config-situation-2073.patch create mode 100644 SOURCES/0028-logging-keep-current-file-mode-of-log-file-if-its-st.patch create mode 100644 SOURCES/0029-DS-VMware-modify-a-few-log-level-4284.patch create mode 100644 SOURCES/0030-NM-renderer-set-default-IPv6-addr-gen-mode-for-all-i.patch delete mode 100644 SOURCES/ci-Align-rhel-custom-files-with-upstream-1431.patch delete mode 100644 SOURCES/ci-Allow-growpart-to-resize-encrypted-partitions-1316.patch delete mode 100644 SOURCES/ci-Ensure-network-ready-before-cloud-init-service-runs-.patch delete mode 100644 SOURCES/ci-Honor-system-locale-for-RHEL-1355.patch delete mode 100644 SOURCES/ci-Remove-rhel-specific-files.patch delete mode 100644 SOURCES/ci-Revert-Revert-Setting-highest-autoconnect-priority-f.patch delete mode 100644 SOURCES/ci-Revert-Setting-highest-autoconnect-priority-for-netw.patch delete mode 100644 SOURCES/ci-Revert-Use-Network-Manager-and-Netplan-as-default-re.patch delete mode 100644 SOURCES/ci-Support-EC2-tags-in-instance-metadata-1309.patch delete mode 100644 SOURCES/ci-Use-Network-Manager-and-Netplan-as-default-renderers.patch delete mode 100644 SOURCES/ci-cc_set_hostname-do-not-write-localhost-when-no-hostn.patch delete mode 100644 SOURCES/ci-cc_set_hostname-ignore-var-lib-cloud-data-set-hostna.patch delete mode 100644 SOURCES/ci-cloud.cfg.tmpl-make-sure-centos-settings-are-identic.patch delete mode 100644 SOURCES/ci-setup.py-adjust-udev-rules-default-path-1513.patch diff --git a/.cloud-init.metadata b/.cloud-init.metadata index 0356978..1426224 100644 --- a/.cloud-init.metadata +++ b/.cloud-init.metadata @@ -1 +1 @@ -830185bb5ce87ad86e4d1c0c62329bb255ec1648 SOURCES/cloud-init-22.1.tar.gz +0b491818abcdce5ba6c1b30c75dd680d6ee3983e SOURCES/23.1.1.tar.gz diff --git a/.gitignore b/.gitignore index bf19bdd..2595433 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/cloud-init-22.1.tar.gz +SOURCES/23.1.1.tar.gz diff --git a/SOURCES/0001-Add-initial-redhat-changes.patch b/SOURCES/0001-Add-initial-redhat-changes.patch index d9ae844..d8bd385 100644 --- a/SOURCES/0001-Add-initial-redhat-changes.patch +++ b/SOURCES/0001-Add-initial-redhat-changes.patch @@ -1,621 +1,61 @@ -From 7daf47d1ee60a132244f2a9ec4e89ad496c32c3e Mon Sep 17 00:00:00 2001 +From c4d66915520554adedff9be7396f877cd1a5525c Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito -Date: Mon, 28 Mar 2022 14:08:05 +0200 -Subject: Add initial redhat setup +Date: Mon, 6 Mar 2023 16:37:20 +0100 +Subject: [PATCH] Add initial redhat changes -Merged patches (22.1): -- 70f80f82 Use _systemdgeneratordir macro for cloud-init-generator handling -- 0f74e7b8 Add dhcp-client as a dependency -- 791eb2b6 Report full specific version with "cloud-init --version" -- 865805d6 source-git: Use dynamic SRPM_NAME -- 45ddc666 add the drop-in also in the %files section of cloud-init.spec -- 08d939b2 Add gdisk and openssl as deps to fix UEFI / Azure initialization -- 0531cd68 Add netifaces package as a Requires in cloud-init.spec.template +Adding minimal set of changes necessary for successful build of the package +on RHEL/CentOS 9 Stream koji. + +Merged patches (23.1.1): +724a80ac Add TargetRelease +967a4405b rhel/cloud.cfg: remove ssh_genkeytypes in settings.py and set in cloud.cfg +^ Merged since it removes hunks added in this commit itself + +Discarded because not needed anymore (packit): +e3fd7ce12 Configure Packit to ignore the .gitignore file +e18654e9 Fixes for packit support + +Discarded because file does not exist anymore and templates are aligned with upstream: +3576b12460bf18557857ee25df6bf530dab66612 Adding _netdev to the default mount configuration +8092b57ab245856ff1fdde1469960608a489c95e Remove rhel specific files + +Added the following entry to %files to keep track of the new README file in config/clean.d/README +%doc %{_sysconfdir}/cloud/clean.d/README + +ignored +c75e509b0 Revert "Revert "Setting highest autoconnect priority for network-scripts"" +0eba5c619 Revert "Setting highest autoconnect priority for network-scripts" + +ignored +ba19343c0d9807d0c68a2d8e4ab274f3ca884247 Add Gitlab CI +fe09305a5479a4814d6c46df07a906bafa29d637 Delete .gitlab-ci.yml Conflicts: -- .gitignore -- cloudinit/config/cc_chef.py = use double quotes instead of single quotes -- cloudinit/settings.py = use rhel settings -- cloudinit/sources/DataSourceAzure.py = remove temporary_hostname and helper -- requirements.txt = just add netifaces and not jsonschema dep -- setup.py = use double quotes instead of single quotes +missing rhel/ static files and "" instead of '' in setup.py Signed-off-by: Emanuele Giuseppe Esposito - -Merged patches (RHEL-9/21.1): -- 5688a1d0 Removing python-nose and python-tox as dependency -- 237d57f9 Removing mock dependency -- d1c2f496 Removing python-jsonschema dependency -- 0d1cd14c Don't override default network configuration - -Merged patches (21.1): -- 915d30ad Change gating file to correct rhel version -- 311f318d Removing net-tools dependency -- 74731806 Adding man pages to Red Hat spec file -- 758d333d Removing blocking test from yaml configuration file -- c7e7c59c Changing permission of cloud-init-generator to 755 -- 8b85abbb Installing man pages in the correct place with correct permissions -- c6808d8d Fix unit failure of cloud-final.service if NetworkManager was not present. -- 11866ef6 Report full specific version with "cloud-init --version" - -Rebase notes (18.5): -- added bash_completition file -- added cloud-id file - -Merged patches (20.3): -- 01900d0 changing ds-identify patch from /usr/lib to /usr/libexec -- 7f47ca3 Render the generator from template instead of cp - -Merged patches (19.4): -- 4ab5a61 Fix for network configuration not persisting after reboot -- 84cf125 Removing cloud-user from wheel -- 31290ab Adding gating tests for Azure, ESXi and AWS - -Merged patches (18.5): -- 2d6b469 add power-state-change module to cloud_final_modules -- 764159f Adding systemd mount options to wait for cloud-init -- da4d99e Adding disk_setup to rhel/cloud.cfg -- f5c6832 Enable cloud-init by default on vmware - -Conflicts: -cloudinit/config/cc_chef.py: -- Updated header documentation text -- Replacing double quotes by simple quotes - -setup.py: -- Adding missing cmdclass info - -Signed-off-by: Eduardo Otubo - -Changes: -- move redhat to .distro to use new build script structure -- Fixing changelog for RHEL 9 - -Merged patches (21.1): -- 69bd7f71 DataSourceAzure.py: use hostnamectl to set hostname -- 0407867e Remove race condition between cloud-init and NetworkManager - -Signed-off-by: Miroslav Rezanina --- - .distro/.gitignore | 1 + - .distro/Makefile | 74 ++++ - .distro/Makefile.common | 20 + - .distro/cloud-init-tmpfiles.conf | 1 + - .distro/cloud-init.spec.template | 505 ++++++++++++++++++++++++++ - .distro/gating.yaml | 8 + - .distro/rpmbuild/BUILD/.gitignore | 3 + - .distro/rpmbuild/RPMS/.gitignore | 3 + - .distro/rpmbuild/SOURCES/.gitignore | 3 + - .distro/rpmbuild/SPECS/.gitignore | 3 + - .distro/rpmbuild/SRPMS/.gitignore | 3 + - .distro/scripts/frh.py | 27 ++ - .distro/scripts/git-backport-diff | 327 +++++++++++++++++ - .distro/scripts/git-compile-check | 215 +++++++++++ - .distro/scripts/process-patches.sh | 88 +++++ - .distro/scripts/tarball_checksum.sh | 3 + - .gitignore | 1 + - cloudinit/config/cc_chef.py | 65 +++- - cloudinit/settings.py | 21 +- - requirements.txt | 3 - - rhel/README.rhel | 5 + - rhel/cloud-init-tmpfiles.conf | 1 + - rhel/cloud.cfg | 69 ++++ - rhel/systemd/cloud-config.service | 18 + - rhel/systemd/cloud-config.target | 11 + - rhel/systemd/cloud-final.service | 24 ++ - rhel/systemd/cloud-init-local.service | 31 ++ - rhel/systemd/cloud-init.service | 26 ++ - rhel/systemd/cloud-init.target | 7 + - setup.py | 28 +- - tools/read-version | 28 +- - 31 files changed, 1557 insertions(+), 65 deletions(-) - create mode 100644 .distro/.gitignore - create mode 100644 .distro/Makefile - create mode 100644 .distro/Makefile.common - create mode 100644 .distro/cloud-init-tmpfiles.conf - create mode 100644 .distro/cloud-init.spec.template - create mode 100644 .distro/gating.yaml - create mode 100644 .distro/rpmbuild/BUILD/.gitignore - create mode 100644 .distro/rpmbuild/RPMS/.gitignore - create mode 100644 .distro/rpmbuild/SOURCES/.gitignore - create mode 100644 .distro/rpmbuild/SPECS/.gitignore - create mode 100644 .distro/rpmbuild/SRPMS/.gitignore - create mode 100755 .distro/scripts/frh.py - create mode 100755 .distro/scripts/git-backport-diff - create mode 100755 .distro/scripts/git-compile-check - create mode 100755 .distro/scripts/process-patches.sh - create mode 100755 .distro/scripts/tarball_checksum.sh - create mode 100644 rhel/README.rhel - create mode 100644 rhel/cloud-init-tmpfiles.conf - create mode 100644 rhel/cloud.cfg - create mode 100644 rhel/systemd/cloud-config.service - create mode 100644 rhel/systemd/cloud-config.target - create mode 100644 rhel/systemd/cloud-final.service - create mode 100644 rhel/systemd/cloud-init-local.service - create mode 100644 rhel/systemd/cloud-init.service - create mode 100644 rhel/systemd/cloud-init.target + cloudinit/settings.py | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) -diff --git a/cloudinit/config/cc_chef.py b/cloudinit/config/cc_chef.py -index fdb3a6e3..d028c548 100644 ---- a/cloudinit/config/cc_chef.py -+++ b/cloudinit/config/cc_chef.py -@@ -6,7 +6,70 @@ - # - # This file is part of cloud-init. See LICENSE file for license information. - --"""Chef: module that configures, starts and installs chef.""" -+""" -+Chef -+---- -+**Summary:** module that configures, starts and installs chef. -+ -+This module enables chef to be installed (from packages or -+from gems, or from omnibus). Before this occurs chef configurations are -+written to disk (validation.pem, client.pem, firstboot.json, client.rb), -+and needed chef folders/directories are created (/etc/chef and /var/log/chef -+and so-on). Then once installing proceeds correctly if configured chef will -+be started (in daemon mode or in non-daemon mode) and then once that has -+finished (if ran in non-daemon mode this will be when chef finishes -+converging, if ran in daemon mode then no further actions are possible since -+chef will have forked into its own process) then a post run function can -+run that can do finishing activities (such as removing the validation pem -+file). -+ -+**Internal name:** ``cc_chef`` -+ -+**Module frequency:** per always -+ -+**Supported distros:** all -+ -+**Config keys**:: -+ -+ chef: -+ directories: (defaulting to /etc/chef, /var/log/chef, /var/lib/chef, -+ /var/cache/chef, /var/backups/chef, /run/chef) -+ validation_cert: (optional string to be written to file validation_key) -+ special value 'system' means set use existing file -+ validation_key: (optional the path for validation_cert. default -+ /etc/chef/validation.pem) -+ firstboot_path: (path to write run_list and initial_attributes keys that -+ should also be present in this configuration, defaults -+ to /etc/chef/firstboot.json) -+ exec: boolean to run or not run chef (defaults to false, unless -+ a gem installed is requested -+ where this will then default -+ to true) -+ -+ chef.rb template keys (if falsey, then will be skipped and not -+ written to /etc/chef/client.rb) -+ -+ chef: -+ client_key: -+ encrypted_data_bag_secret: -+ environment: -+ file_backup_path: -+ file_cache_path: -+ json_attribs: -+ log_level: -+ log_location: -+ node_name: -+ omnibus_url: -+ omnibus_url_retries: -+ omnibus_version: -+ pid_file: -+ server_url: -+ show_time: -+ ssl_verify_mode: -+ validation_cert: -+ validation_key: -+ validation_name: -+""" - - import itertools - import json diff --git a/cloudinit/settings.py b/cloudinit/settings.py -index ecc1403b..a780e21e 100644 +index 8684d003..edbb217d 100644 --- a/cloudinit/settings.py +++ b/cloudinit/settings.py -@@ -48,16 +48,19 @@ CFG_BUILTIN = { - # At the end to act as a 'catch' when none of the above work... - "None", +@@ -53,13 +53,14 @@ CFG_BUILTIN = { ], -- "def_log_file": "/var/log/cloud-init.log", -- "log_cfgs": [], + "def_log_file": "/var/log/cloud-init.log", + "log_cfgs": [], - "syslog_fix_perms": ["syslog:adm", "root:adm", "root:wheel", "root:root"], -- "system_info": { -- "paths": { -- "cloud_dir": "/var/lib/cloud", -- "templates_dir": "/etc/cloud/templates/", -+ 'def_log_file': '/var/log/cloud-init.log', -+ 'log_cfgs': [], -+ 'mount_default_fields': [None, None, 'auto', 'defaults,nofail', '0', '2'], -+ 'ssh_deletekeys': False, -+ 'ssh_genkeytypes': [], -+ 'syslog_fix_perms': [], -+ 'system_info': { -+ 'paths': { -+ 'cloud_dir': '/var/lib/cloud', -+ 'templates_dir': '/etc/cloud/templates/', ++ "mount_default_fields": [None, None, "auto", "defaults,nofail", "0", "2"], ++ "syslog_fix_perms": [], + "system_info": { + "paths": { + "cloud_dir": "/var/lib/cloud", + "templates_dir": "/etc/cloud/templates/", }, - "distro": "ubuntu", -- "network": {"renderers": None}, -+ 'distro': 'rhel', -+ 'network': {'renderers': None}, ++ "distro": "rhel", + "network": {"renderers": None}, }, "vendor_data": {"enabled": True, "prefix": []}, - "vendor_data2": {"enabled": True, "prefix": []}, -diff --git a/requirements.txt b/requirements.txt -index c4adc455..f77f1d73 100644 ---- a/requirements.txt -+++ b/requirements.txt -@@ -30,9 +30,6 @@ requests - # For patching pieces of cloud-config together - jsonpatch - --# For validating cloud-config sections per schema definitions --jsonschema -- - # Used by DataSourceVMware to inspect the host's network configuration during - # the "setup()" function. - # -diff --git a/rhel/README.rhel b/rhel/README.rhel -new file mode 100644 -index 00000000..aa29630d ---- /dev/null -+++ b/rhel/README.rhel -@@ -0,0 +1,5 @@ -+The following cloud-init modules are currently unsupported on this OS: -+ - apt_update_upgrade ('apt_update', 'apt_upgrade', 'apt_mirror', 'apt_preserve_sources_list', 'apt_old_mirror', 'apt_sources', 'debconf_selections', 'packages' options) -+ - byobu ('byobu_by_default' option) -+ - chef -+ - grub_dpkg -diff --git a/rhel/cloud-init-tmpfiles.conf b/rhel/cloud-init-tmpfiles.conf -new file mode 100644 -index 00000000..0c6d2a3b ---- /dev/null -+++ b/rhel/cloud-init-tmpfiles.conf -@@ -0,0 +1 @@ -+d /run/cloud-init 0700 root root - - -diff --git a/rhel/cloud.cfg b/rhel/cloud.cfg -new file mode 100644 -index 00000000..9ecba215 ---- /dev/null -+++ b/rhel/cloud.cfg -@@ -0,0 +1,69 @@ -+users: -+ - default -+ -+disable_root: 1 -+ssh_pwauth: 0 -+ -+mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service', '0', '2'] -+resize_rootfs_tmp: /dev -+ssh_deletekeys: 1 -+ssh_genkeytypes: ~ -+syslog_fix_perms: ~ -+disable_vmware_customization: false -+ -+cloud_init_modules: -+ - disk_setup -+ - migrator -+ - bootcmd -+ - write-files -+ - growpart -+ - resizefs -+ - set_hostname -+ - update_hostname -+ - update_etc_hosts -+ - rsyslog -+ - users-groups -+ - ssh -+ -+cloud_config_modules: -+ - mounts -+ - locale -+ - set-passwords -+ - rh_subscription -+ - yum-add-repo -+ - package-update-upgrade-install -+ - timezone -+ - puppet -+ - chef -+ - salt-minion -+ - mcollective -+ - disable-ec2-metadata -+ - runcmd -+ -+cloud_final_modules: -+ - rightscale_userdata -+ - scripts-per-once -+ - scripts-per-boot -+ - scripts-per-instance -+ - scripts-user -+ - ssh-authkey-fingerprints -+ - keys-to-console -+ - phone-home -+ - final-message -+ - power-state-change -+ -+system_info: -+ default_user: -+ name: cloud-user -+ lock_passwd: true -+ gecos: Cloud User -+ groups: [adm, systemd-journal] -+ sudo: ["ALL=(ALL) NOPASSWD:ALL"] -+ shell: /bin/bash -+ distro: rhel -+ paths: -+ cloud_dir: /var/lib/cloud -+ templates_dir: /etc/cloud/templates -+ ssh_svcname: sshd -+ -+# vim:syntax=yaml -diff --git a/rhel/systemd/cloud-config.service b/rhel/systemd/cloud-config.service -new file mode 100644 -index 00000000..f3dcd4be ---- /dev/null -+++ b/rhel/systemd/cloud-config.service -@@ -0,0 +1,18 @@ -+[Unit] -+Description=Apply the settings specified in cloud-config -+After=network-online.target cloud-config.target -+Wants=network-online.target cloud-config.target -+ConditionPathExists=!/etc/cloud/cloud-init.disabled -+ConditionKernelCommandLine=!cloud-init=disabled -+ -+[Service] -+Type=oneshot -+ExecStart=/usr/bin/cloud-init modules --mode=config -+RemainAfterExit=yes -+TimeoutSec=0 -+ -+# Output needs to appear in instance console output -+StandardOutput=journal+console -+ -+[Install] -+WantedBy=cloud-init.target -diff --git a/rhel/systemd/cloud-config.target b/rhel/systemd/cloud-config.target -new file mode 100644 -index 00000000..ae9b7d02 ---- /dev/null -+++ b/rhel/systemd/cloud-config.target -@@ -0,0 +1,11 @@ -+# cloud-init normally emits a "cloud-config" upstart event to inform third -+# parties that cloud-config is available, which does us no good when we're -+# using systemd. cloud-config.target serves as this synchronization point -+# instead. Services that would "start on cloud-config" with upstart can -+# instead use "After=cloud-config.target" and "Wants=cloud-config.target" -+# as appropriate. -+ -+[Unit] -+Description=Cloud-config availability -+Wants=cloud-init-local.service cloud-init.service -+After=cloud-init-local.service cloud-init.service -diff --git a/rhel/systemd/cloud-final.service b/rhel/systemd/cloud-final.service -new file mode 100644 -index 00000000..e281c0cf ---- /dev/null -+++ b/rhel/systemd/cloud-final.service -@@ -0,0 +1,24 @@ -+[Unit] -+Description=Execute cloud user/final scripts -+After=network-online.target cloud-config.service rc-local.service -+Wants=network-online.target cloud-config.service -+ConditionPathExists=!/etc/cloud/cloud-init.disabled -+ConditionKernelCommandLine=!cloud-init=disabled -+ -+[Service] -+Type=oneshot -+ExecStart=/usr/bin/cloud-init modules --mode=final -+RemainAfterExit=yes -+TimeoutSec=0 -+KillMode=process -+# Restart NetworkManager if it is present and running. -+ExecStartPost=/bin/sh -c 'u=NetworkManager.service; \ -+ out=$(systemctl show --property=SubState $u) || exit; \ -+ [ "$out" = "SubState=running" ] || exit 0; \ -+ systemctl reload-or-try-restart $u' -+ -+# Output needs to appear in instance console output -+StandardOutput=journal+console -+ -+[Install] -+WantedBy=cloud-init.target -diff --git a/rhel/systemd/cloud-init-local.service b/rhel/systemd/cloud-init-local.service -new file mode 100644 -index 00000000..8f9f6c9f ---- /dev/null -+++ b/rhel/systemd/cloud-init-local.service -@@ -0,0 +1,31 @@ -+[Unit] -+Description=Initial cloud-init job (pre-networking) -+DefaultDependencies=no -+Wants=network-pre.target -+After=systemd-remount-fs.service -+Requires=dbus.socket -+After=dbus.socket -+Before=NetworkManager.service network.service -+Before=network-pre.target -+Before=shutdown.target -+Before=firewalld.target -+Conflicts=shutdown.target -+RequiresMountsFor=/var/lib/cloud -+ConditionPathExists=!/etc/cloud/cloud-init.disabled -+ConditionKernelCommandLine=!cloud-init=disabled -+ -+[Service] -+Type=oneshot -+ExecStartPre=/bin/mkdir -p /run/cloud-init -+ExecStartPre=/sbin/restorecon /run/cloud-init -+ExecStartPre=/usr/bin/touch /run/cloud-init/enabled -+ExecStart=/usr/bin/cloud-init init --local -+ExecStart=/bin/touch /run/cloud-init/network-config-ready -+RemainAfterExit=yes -+TimeoutSec=0 -+ -+# Output needs to appear in instance console output -+StandardOutput=journal+console -+ -+[Install] -+WantedBy=cloud-init.target -diff --git a/rhel/systemd/cloud-init.service b/rhel/systemd/cloud-init.service -new file mode 100644 -index 00000000..0b3d796d ---- /dev/null -+++ b/rhel/systemd/cloud-init.service -@@ -0,0 +1,26 @@ -+[Unit] -+Description=Initial cloud-init job (metadata service crawler) -+Wants=cloud-init-local.service -+Wants=sshd-keygen.service -+Wants=sshd.service -+After=cloud-init-local.service -+After=NetworkManager.service network.service -+After=NetworkManager-wait-online.service -+Before=network-online.target -+Before=sshd-keygen.service -+Before=sshd.service -+Before=systemd-user-sessions.service -+ConditionPathExists=!/etc/cloud/cloud-init.disabled -+ConditionKernelCommandLine=!cloud-init=disabled -+ -+[Service] -+Type=oneshot -+ExecStart=/usr/bin/cloud-init init -+RemainAfterExit=yes -+TimeoutSec=0 -+ -+# Output needs to appear in instance console output -+StandardOutput=journal+console -+ -+[Install] -+WantedBy=cloud-init.target -diff --git a/rhel/systemd/cloud-init.target b/rhel/systemd/cloud-init.target -new file mode 100644 -index 00000000..083c3b6f ---- /dev/null -+++ b/rhel/systemd/cloud-init.target -@@ -0,0 +1,7 @@ -+# cloud-init target is enabled by cloud-init-generator -+# To disable it you can either: -+# a.) boot with kernel cmdline of 'cloud-init=disabled' -+# b.) touch a file /etc/cloud/cloud-init.disabled -+[Unit] -+Description=Cloud-init target -+After=multi-user.target -diff --git a/setup.py b/setup.py -index a9132d2c..3c377eaa 100755 ---- a/setup.py -+++ b/setup.py -@@ -139,21 +139,6 @@ INITSYS_FILES = { - "sysvinit_deb": [f for f in glob("sysvinit/debian/*") if is_f(f)], - "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") -- + glob("systemd/*.service") -- + glob("systemd/*.socket") -- + glob("systemd/*.target") -- ) -- if (is_f(f) and not is_generator(f)) -- ], -- "systemd.generators": [ -- render_tmpl(f, mode=0o755) -- for f in glob("systemd/*") -- if is_f(f) and is_generator(f) -- ], - "upstart": [f for f in glob("upstart/*") if is_f(f)], - } - INITSYS_ROOTS = { -@@ -163,10 +148,6 @@ INITSYS_ROOTS = { - "sysvinit_deb": "etc/init.d", - "sysvinit_openrc": "etc/init.d", - "sysvinit_suse": "etc/init.d", -- "systemd": pkg_config_read("systemd", "systemdsystemunitdir"), -- "systemd.generators": pkg_config_read( -- "systemd", "systemdsystemgeneratordir" -- ), - "upstart": "etc/init/", - } - INITSYS_TYPES = sorted([f.partition(".")[0] for f in INITSYS_ROOTS.keys()]) -@@ -281,15 +262,13 @@ data_files = [ - ( - USR_LIB_EXEC + "/cloud-init", - [ -- "tools/ds-identify", - "tools/hook-hotplug", - "tools/uncloud-init", - "tools/write-ssh-key-fingerprints", - ], - ), - ( -- USR + "/share/bash-completion/completions", -- ["bash_completion/cloud-init"], -+ ETC + "/bash_completion.d", ["bash_completion/cloud-init"], - ), - (USR + "/share/doc/cloud-init", [f for f in glob("doc/*") if is_f(f)]), - ( -@@ -308,8 +287,7 @@ if not platform.system().endswith("BSD"): - ETC + "/NetworkManager/dispatcher.d/", - ["tools/hook-network-manager"], - ), -- (ETC + "/dhcp/dhclient-exit-hooks.d/", ["tools/hook-dhclient"]), -- (LIB + "/udev/rules.d", [f for f in glob("udev/*.rules")]), -+ ("/usr/lib/udev/rules.d", [f for f in glob("udev/*.rules")]), - ( - ETC + "/systemd/system/sshd-keygen@.service.d/", - ["systemd/disable-sshd-keygen-if-cloud-init-active.conf"], -@@ -339,8 +317,6 @@ setuptools.setup( - scripts=["tools/cloud-init-per"], - license="Dual-licensed under GPLv3 or Apache 2.0", - data_files=data_files, -- install_requires=requirements, -- cmdclass=cmdclass, - entry_points={ - "console_scripts": [ - "cloud-init = cloudinit.cmd.main:main", -diff --git a/tools/read-version b/tools/read-version -index 02c90643..79755f78 100755 ---- a/tools/read-version -+++ b/tools/read-version -@@ -71,32 +71,8 @@ version_long = None - is_release_branch_ci = ( - os.environ.get("TRAVIS_PULL_REQUEST_BRANCH", "").startswith("upstream/") - ) --if is_gitdir(_tdir) and which("git") and not is_release_branch_ci: -- flags = [] -- if use_tags: -- flags = ['--tags'] -- cmd = ['git', 'describe', '--abbrev=8', '--match=[0-9]*'] + flags -- -- try: -- version = tiny_p(cmd).strip() -- except RuntimeError: -- version = None -- -- if version is None or not version.startswith(src_version): -- sys.stderr.write("git describe version (%s) differs from " -- "cloudinit.version (%s)\n" % (version, src_version)) -- sys.stderr.write( -- "Please get the latest upstream tags.\n" -- "As an example, this can be done with the following:\n" -- "$ git remote add upstream https://git.launchpad.net/cloud-init\n" -- "$ git fetch upstream --tags\n" -- ) -- sys.exit(1) -- -- version_long = tiny_p(cmd + ["--long"]).strip() --else: -- version = src_version -- version_long = None -+version = src_version -+version_long = None - - # version is X.Y.Z[+xxx.gHASH] - # version_long is None or X.Y.Z-xxx-gHASH --- -2.31.1 - diff --git a/SOURCES/0002-Do-not-write-NM_CONTROLLED-no-in-generated-interface.patch b/SOURCES/0002-Do-not-write-NM_CONTROLLED-no-in-generated-interface.patch index a686f6d..2d32e2c 100644 --- a/SOURCES/0002-Do-not-write-NM_CONTROLLED-no-in-generated-interface.patch +++ b/SOURCES/0002-Do-not-write-NM_CONTROLLED-no-in-generated-interface.patch @@ -1,7 +1,8 @@ -From c521ec2ce5b1d9a7322ce152011b8792f121bf5c Mon Sep 17 00:00:00 2001 +From b3b96bff187e9d0bfcbfefd5fca05c61bd50d368 Mon Sep 17 00:00:00 2001 From: Eduardo Otubo Date: Fri, 7 May 2021 13:36:06 +0200 -Subject: Do not write NM_CONTROLLED=no in generated interface config files +Subject: [PATCH] Do not write NM_CONTROLLED=no in generated interface config + files Conflicts 20.3: - Not appplying patch on cloudinit/net/sysconfig.py since it now has a @@ -20,10 +21,10 @@ Signed-off-by: Ryan McCabe 2 files changed, 10 insertions(+), 30 deletions(-) diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py -index ba85c4f6..d8c53312 100644 +index d4daa78f..a7dbe55b 100644 --- a/cloudinit/net/sysconfig.py +++ b/cloudinit/net/sysconfig.py -@@ -336,7 +336,6 @@ class Renderer(renderer.Renderer): +@@ -316,7 +316,6 @@ class Renderer(renderer.Renderer): "rhel": { "ONBOOT": True, "USERCTL": False, @@ -31,7 +32,7 @@ index ba85c4f6..d8c53312 100644 "BOOTPROTO": "none", }, "suse": {"BOOTPROTO": "static", "STARTMODE": "auto"}, -@@ -1039,7 +1038,16 @@ class Renderer(renderer.Renderer): +@@ -1019,7 +1018,16 @@ 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)) @@ -50,10 +51,10 @@ index ba85c4f6..d8c53312 100644 netcfg.append("NETWORKING_IPV6=yes") netcfg.append("IPV6_AUTOCONF=no") diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py -index 47e4ba00..591241b3 100644 +index 056aaeb6..0f523ff8 100644 --- a/tests/unittests/test_net.py +++ b/tests/unittests/test_net.py -@@ -579,7 +579,6 @@ GATEWAY=172.19.3.254 +@@ -585,7 +585,6 @@ GATEWAY=172.19.3.254 HWADDR=fa:16:3e:ed:9a:59 IPADDR=172.19.1.34 NETMASK=255.255.252.0 @@ -61,7 +62,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -712,7 +711,6 @@ IPADDR=172.19.1.34 +@@ -749,7 +748,6 @@ IPADDR=172.19.1.34 IPADDR1=10.0.0.10 NETMASK=255.255.252.0 NETMASK1=255.255.255.0 @@ -69,7 +70,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -874,7 +872,6 @@ IPV6_AUTOCONF=no +@@ -911,7 +909,6 @@ IPV6_AUTOCONF=no IPV6_DEFAULTGW=2001:DB8::1 IPV6_FORCE_ACCEPT_RA=no NETMASK=255.255.252.0 @@ -77,7 +78,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -1053,7 +1050,6 @@ NETWORK_CONFIGS = { +@@ -1090,7 +1087,6 @@ NETWORK_CONFIGS = { BOOTPROTO=none DEVICE=eth1 HWADDR=cf:d6:af:48:e8:80 @@ -85,7 +86,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no""" -@@ -1072,7 +1068,6 @@ NETWORK_CONFIGS = { +@@ -1109,7 +1105,6 @@ NETWORK_CONFIGS = { IPADDR=192.168.21.3 NETMASK=255.255.255.0 METRIC=10000 @@ -93,7 +94,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no""" -@@ -1244,7 +1239,6 @@ NETWORK_CONFIGS = { +@@ -1353,7 +1348,6 @@ NETWORK_CONFIGS = { IPV6_AUTOCONF=no IPV6_FORCE_ACCEPT_RA=no NETMASK=255.255.255.0 @@ -101,7 +102,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -2093,7 +2087,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -2377,7 +2371,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 @@ -109,7 +110,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Bond USERCTL=no""" -@@ -2103,7 +2096,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -2387,7 +2380,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 @@ -117,7 +118,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes PHYSDEV=bond0 USERCTL=no -@@ -2123,7 +2115,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -2407,7 +2399,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 @@ -125,7 +126,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes PRIO=22 STP=no -@@ -2135,7 +2126,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -2419,7 +2410,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 @@ -133,7 +134,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no""" -@@ -2154,7 +2144,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -2438,7 +2428,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 @@ -141,7 +142,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes PHYSDEV=eth0 USERCTL=no -@@ -2166,7 +2155,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -2450,7 +2439,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 @@ -149,7 +150,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes SLAVE=yes TYPE=Ethernet -@@ -2178,7 +2166,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -2462,7 +2450,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 @@ -157,7 +158,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes SLAVE=yes TYPE=Ethernet -@@ -2190,7 +2177,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -2474,7 +2461,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 @@ -165,7 +166,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no""" -@@ -2201,7 +2187,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -2485,7 +2471,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 @@ -173,7 +174,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no""" -@@ -2212,7 +2197,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true +@@ -2496,7 +2481,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 @@ -181,7 +182,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=no TYPE=Ethernet USERCTL=no""" -@@ -2689,7 +2673,6 @@ iface bond0 inet6 static +@@ -3220,7 +3204,6 @@ iface bond0 inet6 static MTU=9000 NETMASK=255.255.255.0 NETMASK1=255.255.255.0 @@ -189,7 +190,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Bond USERCTL=no -@@ -2701,7 +2684,6 @@ iface bond0 inet6 static +@@ -3232,7 +3215,6 @@ iface bond0 inet6 static DEVICE=bond0s0 HWADDR=aa:bb:cc:dd:e8:00 MASTER=bond0 @@ -197,7 +198,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes SLAVE=yes TYPE=Ethernet -@@ -2729,7 +2711,6 @@ iface bond0 inet6 static +@@ -3260,7 +3242,6 @@ iface bond0 inet6 static DEVICE=bond0s1 HWADDR=aa:bb:cc:dd:e8:01 MASTER=bond0 @@ -205,7 +206,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes SLAVE=yes TYPE=Ethernet -@@ -2794,7 +2775,6 @@ iface bond0 inet6 static +@@ -3406,7 +3387,6 @@ iface bond0 inet6 static BOOTPROTO=none DEVICE=en0 HWADDR=aa:bb:cc:dd:e8:00 @@ -213,7 +214,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no""" -@@ -2815,7 +2795,6 @@ iface bond0 inet6 static +@@ -3427,7 +3407,6 @@ iface bond0 inet6 static MTU=2222 NETMASK=255.255.255.0 NETMASK1=255.255.255.0 @@ -221,7 +222,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes PHYSDEV=en0 USERCTL=no -@@ -2890,7 +2869,6 @@ iface bond0 inet6 static +@@ -3553,7 +3532,6 @@ iface bond0 inet6 static DEVICE=br0 IPADDR=192.168.2.2 NETMASK=255.255.255.0 @@ -229,7 +230,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes PRIO=22 STP=no -@@ -3032,7 +3010,6 @@ iface bond0 inet6 static +@@ -3769,7 +3747,6 @@ iface bond0 inet6 static HWADDR=52:54:00:12:34:00 IPADDR=192.168.1.2 NETMASK=255.255.255.0 @@ -237,7 +238,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=no TYPE=Ethernet USERCTL=no -@@ -3044,7 +3021,6 @@ iface bond0 inet6 static +@@ -3781,7 +3758,6 @@ iface bond0 inet6 static DEVICE=eth1 HWADDR=52:54:00:12:34:aa MTU=1480 @@ -245,7 +246,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -3055,7 +3031,6 @@ iface bond0 inet6 static +@@ -3792,7 +3768,6 @@ iface bond0 inet6 static BOOTPROTO=none DEVICE=eth2 HWADDR=52:54:00:12:34:ff @@ -253,7 +254,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=no TYPE=Ethernet USERCTL=no -@@ -3628,7 +3603,6 @@ class TestRhelSysConfigRendering(CiTestCase): +@@ -4469,7 +4444,6 @@ class TestRhelSysConfigRendering(CiTestCase): BOOTPROTO=dhcp DEVICE=eth1000 HWADDR=07-1c-c6-75-a4-be @@ -261,7 +262,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -3840,7 +3814,6 @@ GATEWAY=10.0.2.2 +@@ -4681,7 +4655,6 @@ GATEWAY=10.0.2.2 HWADDR=52:54:00:12:34:00 IPADDR=10.0.2.15 NETMASK=255.255.255.0 @@ -269,7 +270,7 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no -@@ -3910,7 +3883,6 @@ USERCTL=no +@@ -4751,7 +4724,6 @@ USERCTL=no # BOOTPROTO=dhcp DEVICE=eth0 @@ -277,6 +278,3 @@ index 47e4ba00..591241b3 100644 ONBOOT=yes TYPE=Ethernet USERCTL=no --- -2.31.1 - diff --git a/SOURCES/0003-Adding-_netdev-to-the-default-mount-configuration.patch b/SOURCES/0003-Adding-_netdev-to-the-default-mount-configuration.patch deleted file mode 100644 index 0f57fed..0000000 --- a/SOURCES/0003-Adding-_netdev-to-the-default-mount-configuration.patch +++ /dev/null @@ -1,42 +0,0 @@ -From b952fa472be3f417e0d857c8647a1b930624c247 Mon Sep 17 00:00:00 2001 -From: Eduardo Otubo -Date: Fri, 25 Feb 2022 05:05:17 -0500 -Subject: Adding _netdev to the default mount configuration - -RH-Author: Eduardo Otubo -RH-MergeRequest: 21: Adding _netdev to the default mount configuration -RH-Commit: [1/1] 250860a24db396a5088d207d6526a0028ac73eb3 (otubo/cloud-init-src) -RH-Bugzilla: 1998445 -RH-Acked-by: Miroslav Rezanina -RH-Acked-by: Emanuele Giuseppe Esposito - -Adding _netdev option also to the default configuration for RHEL. - -rhbz: 1998445 -x-downstream-only: yes - -Signed-off-by: Eduardo Otubo - -patch_name: ci-Adding-_netdev-to-the-default-mount-configuration.patch -present_in_specfile: true -location_in_specfile: 29 ---- - rhel/cloud.cfg | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/rhel/cloud.cfg b/rhel/cloud.cfg -index 9ecba215..1ec1a6c6 100644 ---- a/rhel/cloud.cfg -+++ b/rhel/cloud.cfg -@@ -4,7 +4,7 @@ users: - disable_root: 1 - ssh_pwauth: 0 - --mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service', '0', '2'] -+mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service,_netdev', '0', '2'] - resize_rootfs_tmp: /dev - ssh_deletekeys: 1 - ssh_genkeytypes: ~ --- -2.31.1 - diff --git a/SOURCES/0004-Setting-highest-autoconnect-priority-for-network-scr.patch b/SOURCES/0003-Setting-highest-autoconnect-priority-for-network-scr.patch similarity index 80% rename from SOURCES/0004-Setting-highest-autoconnect-priority-for-network-scr.patch rename to SOURCES/0003-Setting-highest-autoconnect-priority-for-network-scr.patch index 690a02f..c9b7740 100644 --- a/SOURCES/0004-Setting-highest-autoconnect-priority-for-network-scr.patch +++ b/SOURCES/0003-Setting-highest-autoconnect-priority-for-network-scr.patch @@ -1,7 +1,7 @@ -From a14df44ffdc880ae16c691901e2671458ab234ff Mon Sep 17 00:00:00 2001 +From c589da20eb92231ef08e10c9724e3e6c663e6ce2 Mon Sep 17 00:00:00 2001 From: Eduardo Otubo Date: Thu, 17 Feb 2022 15:32:35 +0100 -Subject: Setting highest autoconnect priority for network-scripts +Subject: [PATCH] Setting highest autoconnect priority for network-scripts RH-Author: Eduardo Otubo RH-MergeRequest: 22: Setting highest autoconnect priority for network-scripts @@ -24,19 +24,15 @@ rhbz: 2036060 x-downstream-only: yes Signed-off-by: Eduardo Otubo - -patch_name: ci-Setting-highest-autoconnect-priority-for-network-scr.patch -present_in_specfile: true -location_in_specfile: 30 --- cloudinit/net/sysconfig.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py -index d8c53312..b50035b5 100644 +index a7dbe55b..4262cd48 100644 --- a/cloudinit/net/sysconfig.py +++ b/cloudinit/net/sysconfig.py -@@ -337,6 +337,7 @@ class Renderer(renderer.Renderer): +@@ -317,6 +317,7 @@ class Renderer(renderer.Renderer): "ONBOOT": True, "USERCTL": False, "BOOTPROTO": "none", @@ -44,6 +40,3 @@ index d8c53312..b50035b5 100644 }, "suse": {"BOOTPROTO": "static", "STARTMODE": "auto"}, } --- -2.31.1 - diff --git a/SOURCES/0005-limit-permissions-on-def_log_file.patch b/SOURCES/0004-limit-permissions-on-def_log_file.patch similarity index 75% rename from SOURCES/0005-limit-permissions-on-def_log_file.patch rename to SOURCES/0004-limit-permissions-on-def_log_file.patch index ed1072e..e69dd15 100644 --- a/SOURCES/0005-limit-permissions-on-def_log_file.patch +++ b/SOURCES/0004-limit-permissions-on-def_log_file.patch @@ -1,7 +1,7 @@ -From 40ad855b883050069393b9c00db2a6d222d949db Mon Sep 17 00:00:00 2001 +From dfff374f66904e84fb07ca157ba010fac6b5f1de Mon Sep 17 00:00:00 2001 From: Eduardo Otubo Date: Fri, 7 May 2021 13:36:08 +0200 -Subject: limit permissions on def_log_file +Subject: [PATCH] limit permissions on def_log_file This sets a default mode of 0600 on def_log_file, and makes this configurable via the def_log_file_mode option in cloud.cfg. @@ -13,7 +13,10 @@ X-approved-upstream: true Conflicts 21.1: cloudinit/stages.py: adjusting call of ensure_file() to use more recent version +Confilicts 23.1.1: + use "" instead of '' +Signed-off-by: Emanuele Giuseppe Esposito Signed-off-by: Eduardo Otubo --- cloudinit/settings.py | 1 + @@ -22,22 +25,22 @@ Signed-off-by: Eduardo Otubo 3 files changed, 6 insertions(+) diff --git a/cloudinit/settings.py b/cloudinit/settings.py -index a780e21e..aa2d6b95 100644 +index edbb217d..3d541141 100644 --- a/cloudinit/settings.py +++ b/cloudinit/settings.py -@@ -49,6 +49,7 @@ CFG_BUILTIN = { +@@ -52,6 +52,7 @@ CFG_BUILTIN = { "None", ], - 'def_log_file': '/var/log/cloud-init.log', -+ 'def_log_file_mode': 0o600, - 'log_cfgs': [], - 'mount_default_fields': [None, None, 'auto', 'defaults,nofail', '0', '2'], - 'ssh_deletekeys': False, + "def_log_file": "/var/log/cloud-init.log", ++ "def_log_file_mode": 0o600, + "log_cfgs": [], + "mount_default_fields": [None, None, "auto", "defaults,nofail", "0", "2"], + "syslog_fix_perms": [], diff --git a/cloudinit/stages.py b/cloudinit/stages.py -index 3f17294b..61db1dbd 100644 +index 9494a0bf..a624a6fb 100644 --- a/cloudinit/stages.py +++ b/cloudinit/stages.py -@@ -205,6 +205,7 @@ class Init(object): +@@ -202,6 +202,7 @@ class Init: def _initialize_filesystem(self): util.ensure_dirs(self._initial_subdirs()) log_file = util.get_cfg_option_str(self.cfg, "def_log_file") @@ -46,10 +49,10 @@ index 3f17294b..61db1dbd 100644 util.ensure_file(log_file, mode=0o640, preserve_mode=True) perms = self.cfg.get("syslog_fix_perms") diff --git a/doc/examples/cloud-config.txt b/doc/examples/cloud-config.txt -index a2b4a3fa..0ccf3147 100644 +index 15d788f3..b6d16c9c 100644 --- a/doc/examples/cloud-config.txt +++ b/doc/examples/cloud-config.txt -@@ -414,10 +414,14 @@ timezone: US/Eastern +@@ -383,10 +383,14 @@ timezone: US/Eastern # if syslog_fix_perms is a list, it will iterate through and use the # first pair that does not raise error. # @@ -64,6 +67,3 @@ index a2b4a3fa..0ccf3147 100644 syslog_fix_perms: syslog:root # you can set passwords for a user or multiple users --- -2.31.1 - diff --git a/SOURCES/0005-Manual-revert-Use-Network-Manager-and-Netplan-as-def.patch b/SOURCES/0005-Manual-revert-Use-Network-Manager-and-Netplan-as-def.patch new file mode 100644 index 0000000..b1d3933 --- /dev/null +++ b/SOURCES/0005-Manual-revert-Use-Network-Manager-and-Netplan-as-def.patch @@ -0,0 +1,92 @@ +From ecae81f98ce230266eb99671b74534a4ede660f0 Mon Sep 17 00:00:00 2001 +From: Emanuele Giuseppe Esposito +Date: Fri, 10 Mar 2023 11:51:48 +0100 +Subject: [PATCH] Manual revert "Use Network-Manager and Netplan as default + renderers for RHEL and Fedora (#1465)" + +This reverts changes done in commit 7703aa98b. +Done by hand because the doc file affected by that commit has changed. + +X-downstream-only: true + +Signed-off-by: Emanuele Giuseppe Esposito +--- + cloudinit/net/renderers.py | 1 - + config/cloud.cfg.tmpl | 3 --- + doc/rtd/reference/network-config.rst | 16 ++-------------- + 3 files changed, 2 insertions(+), 18 deletions(-) + +diff --git a/cloudinit/net/renderers.py b/cloudinit/net/renderers.py +index fcf7feba..b241683f 100644 +--- a/cloudinit/net/renderers.py ++++ b/cloudinit/net/renderers.py +@@ -30,7 +30,6 @@ DEFAULT_PRIORITY = [ + "eni", + "sysconfig", + "netplan", +- "network-manager", + "freebsd", + "netbsd", + "openbsd", +diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl +index 7238c102..12f32c51 100644 +--- a/config/cloud.cfg.tmpl ++++ b/config/cloud.cfg.tmpl +@@ -381,9 +381,6 @@ system_info: + {% elif variant in ["dragonfly"] %} + network: + renderers: ['freebsd'] +-{% elif variant in ["fedora"] or is_rhel %} +- network: +- renderers: ['netplan', 'network-manager', 'networkd', 'sysconfig', 'eni'] + {% elif variant == "openmandriva" %} + network: + renderers: ['network-manager', 'networkd'] +diff --git a/doc/rtd/reference/network-config.rst b/doc/rtd/reference/network-config.rst +index ea331f1c..bc52afa5 100644 +--- a/doc/rtd/reference/network-config.rst ++++ b/doc/rtd/reference/network-config.rst +@@ -176,16 +176,6 @@ this state, ``cloud-init`` delegates rendering of the configuration to + distro-supported formats. The following ``renderers`` are supported in + ``cloud-init``: + +-NetworkManager +--------------- +- +-`NetworkManager`_ is the standard Linux network configuration tool suite. It +-supports a wide range of networking setups. Configuration is typically stored +-in :file:`/etc/NetworkManager`. +- +-It is the default for a number of Linux distributions; notably Fedora, +-CentOS/RHEL, and their derivatives. +- + ENI + --- + +@@ -223,7 +213,6 @@ preference) is as follows: + - ENI + - Sysconfig + - Netplan +-- NetworkManager + - FreeBSD + - NetBSD + - OpenBSD +@@ -234,7 +223,6 @@ preference) is as follows: + + - **ENI**: using ``ifup``, ``ifdown`` to manage device setup/teardown + - **Netplan**: using ``netplan apply`` to manage device setup/teardown +-- **NetworkManager**: using ``nmcli`` to manage device setup/teardown + - **Networkd**: using ``ip`` to manage device setup/teardown + + When applying the policy, ``cloud-init`` checks if the current instance has the +@@ -244,8 +232,8 @@ supplying an updated configuration in cloud-config. :: + + system_info: + network: +- renderers: ['netplan', 'network-manager', 'eni', 'sysconfig', 'freebsd', 'netbsd', 'openbsd'] +- activators: ['eni', 'netplan', 'network-manager', 'networkd'] ++ renderers: ['netplan', 'eni', 'sysconfig', 'freebsd', 'netbsd', 'openbsd'] ++ activators: ['eni', 'netplan', 'networkd'] + + Network configuration tools + =========================== diff --git a/SOURCES/ci-Revert-Add-native-NetworkManager-support-1224.patch b/SOURCES/0006-Revert-Add-native-NetworkManager-support-1224.patch similarity index 60% rename from SOURCES/ci-Revert-Add-native-NetworkManager-support-1224.patch rename to SOURCES/0006-Revert-Add-native-NetworkManager-support-1224.patch index 981473c..8941797 100644 --- a/SOURCES/ci-Revert-Add-native-NetworkManager-support-1224.patch +++ b/SOURCES/0006-Revert-Add-native-NetworkManager-support-1224.patch @@ -1,38 +1,28 @@ -From 35bd50e66f636a3f3923b6980bdee3ba33f7457d Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Mon, 8 Aug 2022 10:01:16 +0200 -Subject: [PATCH 1/3] Revert "Add native NetworkManager support (#1224)" +From b1dd14ffafad2d2ca84326c525962b2ca086b292 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Wed, 22 Mar 2023 16:31:58 +0530 +Subject: [PATCH] Revert "Add native NetworkManager support (#1224)" -RH-Author: Emanuele Giuseppe Esposito -RH-MergeRequest: 31: Revert "Revert "Setting highest autoconnect priority for network-scripts"" -RH-Commit: [1/3] 38dcbc9ec19412601e96305fcac09642c89d73b8 (eesposit/cloud-init-centos-) -RH-Bugzilla: 2107463 2104389 2117532 2098501 -RH-Acked-by: Eduardo Otubo -RH-Acked-by: Vitaly Kuznetsov -RH-Acked-by: Mohamed Gamal Morsy +This reverts commit feda344e6cf9d37b09bc13cf333a717d1654c26c. -NM is still not stable, revert it for now. - -This reverts commit 588deeb5b3f87ffe40d9ecaf6da3639176f806c4. - -Signed-off-by: Emanuele Giuseppe Esposito +Signed-off-by: Ani Sinha --- - cloudinit/cmd/devel/net_convert.py | 14 +- - cloudinit/net/activators.py | 25 +- - cloudinit/net/network_manager.py | 377 ------- - cloudinit/net/renderers.py | 3 - - cloudinit/net/sysconfig.py | 37 +- - tests/unittests/test_net.py | 1268 +++--------------------- - tests/unittests/test_net_activators.py | 93 +- - 7 files changed, 193 insertions(+), 1624 deletions(-) + cloudinit/cmd/devel/net_convert.py | 14 +- + cloudinit/net/activators.py | 25 +- + cloudinit/net/network_manager.py | 393 ---------------- + cloudinit/net/renderers.py | 2 - + cloudinit/net/sysconfig.py | 42 +- + tests/unittests/test_net.py | 597 +++++-------------------- + tests/unittests/test_net_activators.py | 11 +- + 7 files changed, 161 insertions(+), 923 deletions(-) delete mode 100644 cloudinit/net/network_manager.py diff --git a/cloudinit/cmd/devel/net_convert.py b/cloudinit/cmd/devel/net_convert.py -index 647fe07b..18b1e7ff 100755 +index eee49860..1a0a31ac 100755 --- a/cloudinit/cmd/devel/net_convert.py +++ b/cloudinit/cmd/devel/net_convert.py -@@ -7,14 +7,7 @@ import os - import sys +@@ -10,14 +10,7 @@ import sys + import yaml from cloudinit import distros, log, safeyaml -from cloudinit.net import ( @@ -45,9 +35,9 @@ index 647fe07b..18b1e7ff 100755 -) +from cloudinit.net import eni, netplan, network_state, networkd, sysconfig from cloudinit.sources import DataSourceAzure as azure - from cloudinit.sources import DataSourceOVF as ovf from cloudinit.sources.helpers import openstack -@@ -81,7 +74,7 @@ def get_parser(parser=None): + from cloudinit.sources.helpers.vmware.imc import guestcust_util +@@ -84,7 +77,7 @@ def get_parser(parser=None): parser.add_argument( "-O", "--output-kind", @@ -56,7 +46,7 @@ index 647fe07b..18b1e7ff 100755 required=True, help="The network config format to emit", ) -@@ -155,9 +148,6 @@ def handle_args(name, args): +@@ -157,9 +150,6 @@ def handle_args(name, args): elif args.output_kind == "sysconfig": r_cls = sysconfig.Renderer config = distro.renderer_configs.get("sysconfig") @@ -67,7 +57,7 @@ index 647fe07b..18b1e7ff 100755 raise RuntimeError("Invalid output_kind") diff --git a/cloudinit/net/activators.py b/cloudinit/net/activators.py -index edbc0c06..e80c26df 100644 +index 7d11a02c..d9a8c4d7 100644 --- a/cloudinit/net/activators.py +++ b/cloudinit/net/activators.py @@ -1,14 +1,15 @@ @@ -75,7 +65,7 @@ index edbc0c06..e80c26df 100644 import logging +import os from abc import ABC, abstractmethod - from typing import Iterable, List, Type + from typing import Dict, Iterable, List, Optional, Type, Union from cloudinit import subp, util from cloudinit.net.eni import available as eni_available @@ -131,10 +121,10 @@ index edbc0c06..e80c26df 100644 diff --git a/cloudinit/net/network_manager.py b/cloudinit/net/network_manager.py deleted file mode 100644 -index 79b0fe0b..00000000 +index 53763d15..00000000 --- a/cloudinit/net/network_manager.py +++ /dev/null -@@ -1,377 +0,0 @@ +@@ -1,393 +0,0 @@ -# Copyright 2022 Red Hat, Inc. -# -# Author: Lubomir Rintel @@ -148,15 +138,16 @@ index 79b0fe0b..00000000 -import itertools -import os -import uuid +-from typing import Optional - -from cloudinit import log as logging -from cloudinit import subp, util -- --from . import renderer --from .network_state import is_ipv6_addr, subnet_is_ipv6 +-from cloudinit.net import is_ipv6_address, renderer, subnet_is_ipv6 +-from cloudinit.net.network_state import NetworkState - -NM_RUN_DIR = "/etc/NetworkManager" -NM_LIB_DIR = "/usr/lib/NetworkManager" +-NM_CFG_FILE = "/etc/NetworkManager/NetworkManager.conf" -LOG = logging.getLogger(__name__) - - @@ -205,7 +196,7 @@ index 79b0fe0b..00000000 - - method_map = { - "static": "manual", -- "dhcp6": "dhcp", +- "dhcp6": "auto", - "ipv6_slaac": "auto", - "ipv6_dhcpv6-stateless": "auto", - "ipv6_dhcpv6-stateful": "auto", @@ -232,8 +223,6 @@ index 79b0fe0b..00000000 - - self.config[family]["method"] = method - self._set_default(family, "may-fail", "false") -- if family == "ipv6": -- self._set_default(family, "addr-gen-mode", "stable-privacy") - - def _add_numbered(self, section, key_prefix, value): - """ @@ -274,7 +263,7 @@ index 79b0fe0b..00000000 - # together. We might be getting an IPv6 name server while - # we're dealing with an IPv4 subnet. Sort this out by figuring - # out the correct family and making sure a valid section exist. -- family = "ipv6" if is_ipv6_addr(dns) else "ipv4" +- family = "ipv6" if is_ipv6_address(dns) else "ipv4" - self._set_default(family, "method", "disabled") - - self._set_default(family, "dns", "") @@ -480,7 +469,12 @@ index 79b0fe0b..00000000 - # Well, what can we do... - return con_id - -- def render_network_state(self, network_state, templates=None, target=None): +- def render_network_state( +- self, +- network_state: NetworkState, +- templates: Optional[dict] = None, +- target=None, +- ) -> None: - # First pass makes sure there's NMConnections for all known - # interfaces that have UUIDs that can be linked to from related - # interfaces @@ -507,16 +501,28 @@ index 79b0fe0b..00000000 - - -def available(target=None): -- target_nm_dir = subp.target_path(target, NM_LIB_DIR) -- return os.path.exists(target_nm_dir) +- # TODO: Move `uses_systemd` to a more appropriate location +- # It is imported here to avoid circular import +- from cloudinit.distros import uses_systemd +- +- config_present = os.path.isfile(subp.target_path(target, path=NM_CFG_FILE)) +- nmcli_present = subp.which("nmcli", target=target) +- service_active = True +- if uses_systemd(): +- try: +- subp.subp(["systemctl", "is-enabled", "NetworkManager.service"]) +- except subp.ProcessExecutionError: +- service_active = False +- +- return config_present and bool(nmcli_present) and service_active - - -# vi: ts=4 expandtab diff --git a/cloudinit/net/renderers.py b/cloudinit/net/renderers.py -index 7edc34b5..c755f04c 100644 +index b241683f..c92b9dcf 100644 --- a/cloudinit/net/renderers.py +++ b/cloudinit/net/renderers.py -@@ -8,7 +8,6 @@ from . import ( +@@ -8,7 +8,6 @@ from cloudinit.net import ( freebsd, netbsd, netplan, @@ -532,31 +538,34 @@ index 7edc34b5..c755f04c 100644 "networkd": networkd, "openbsd": openbsd, "sysconfig": sysconfig, -@@ -30,7 +28,6 @@ DEFAULT_PRIORITY = [ - "eni", - "sysconfig", - "netplan", -- "network-manager", - "freebsd", - "netbsd", - "openbsd", diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py -index dc401d78..d8c53312 100644 +index 4262cd48..765c248a 100644 --- a/cloudinit/net/sysconfig.py +++ b/cloudinit/net/sysconfig.py -@@ -5,6 +5,8 @@ import io - import os +@@ -6,6 +6,8 @@ import os import re + from typing import Mapping, Optional +from configobj import ConfigObj + from cloudinit import log as logging from cloudinit import subp, util from cloudinit.distros.parsers import networkmanager_conf, resolv_conf -@@ -64,6 +66,24 @@ def _quote_value(value): +@@ -35,7 +37,7 @@ KNOWN_DISTROS = [ + "TencentOS", + "virtuozzo", + ] +- ++NM_CFG_FILE = "/etc/NetworkManager/NetworkManager.conf" + + def _make_header(sep="#"): + lines = [ +@@ -66,7 +68,26 @@ def _quote_value(value): return value +-class ConfigMap: ++ +def enable_ifcfg_rh(path): + """Add ifcfg-rh to NetworkManager.cfg plugins if main section is present""" + config = ConfigObj(path) @@ -575,10 +584,11 @@ index dc401d78..d8c53312 100644 + LOG.debug("Enabled ifcfg-rh NetworkManager plugins") + + - class ConfigMap(object): ++class ConfigMap(object): """Sysconfig like dictionary object.""" -@@ -1011,6 +1031,8 @@ class Renderer(renderer.Renderer): + # Why does redhat prefer yes/no to true/false?? +@@ -1014,6 +1035,8 @@ class Renderer(renderer.Renderer): netrules_content = self._render_persistent_net(network_state) netrules_path = subp.target_path(target, self.netrules_path) util.write_file(netrules_path, netrules_content, file_mode) @@ -587,7 +597,7 @@ index dc401d78..d8c53312 100644 sysconfig_path = subp.target_path(target, templates.get("control")) # Distros configuring /etc/sysconfig/network as a file e.g. Centos -@@ -1049,9 +1071,14 @@ def _supported_vlan_names(rdev, vid): +@@ -1052,9 +1075,14 @@ def _supported_vlan_names(rdev, vid): def available(target=None): @@ -604,7 +614,7 @@ index dc401d78..d8c53312 100644 expected = ["ifup", "ifdown"] search = ["/sbin", "/usr/sbin"] for p in expected: -@@ -1068,4 +1095,10 @@ def available(target=None): +@@ -1071,4 +1099,10 @@ def available(target=None): return False @@ -616,18 +626,18 @@ index dc401d78..d8c53312 100644 + # vi: ts=4 expandtab diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py -index ef21ad76..591241b3 100644 +index 0f523ff8..4434b350 100644 --- a/tests/unittests/test_net.py +++ b/tests/unittests/test_net.py -@@ -21,7 +21,6 @@ from cloudinit.net import ( - interface_has_own_mac, +@@ -23,7 +23,6 @@ from cloudinit.net import ( + mask_and_ipv4_to_bcast_addr, natural_sort_key, netplan, - network_manager, network_state, networkd, renderers, -@@ -612,37 +611,6 @@ dns = none +@@ -617,37 +616,6 @@ dns = none ), ), ], @@ -665,7 +675,7 @@ index ef21ad76..591241b3 100644 }, { "in_data": { -@@ -1105,50 +1073,6 @@ NETWORK_CONFIGS = { +@@ -1110,50 +1078,6 @@ NETWORK_CONFIGS = { USERCTL=no""" ), }, @@ -716,208 +726,7 @@ index ef21ad76..591241b3 100644 "yaml": textwrap.dedent( """ version: 1 -@@ -1221,34 +1145,6 @@ NETWORK_CONFIGS = { - STARTMODE=auto""" - ) - }, -- "expected_network_manager": { -- "cloud-init-iface0.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init iface0 -- uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 -- type=ethernet -- interface-name=iface0 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- -- [ipv4] -- method=auto -- may-fail=false -- -- [ipv6] -- method=dhcp -- may-fail=false -- addr-gen-mode=stable-privacy -- -- """ -- ), -- }, - "yaml": textwrap.dedent( - """\ - version: 1 -@@ -1351,37 +1247,6 @@ NETWORK_CONFIGS = { - """ - ), - }, -- "expected_network_manager": { -- "cloud-init-iface0.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init iface0 -- uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 -- type=ethernet -- interface-name=iface0 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- mtu=9000 -- -- [ipv4] -- method=manual -- may-fail=false -- address1=192.168.14.2/24 -- -- [ipv6] -- method=manual -- may-fail=false -- addr-gen-mode=stable-privacy -- address1=2001:1::1/64 -- -- """ -- ), -- }, - }, - "v6_and_v4": { - "expected_sysconfig_opensuse": { -@@ -1392,34 +1257,6 @@ NETWORK_CONFIGS = { - STARTMODE=auto""" - ) - }, -- "expected_network_manager": { -- "cloud-init-iface0.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init iface0 -- uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 -- type=ethernet -- interface-name=iface0 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- -- [ipv6] -- method=dhcp -- may-fail=false -- addr-gen-mode=stable-privacy -- -- [ipv4] -- method=auto -- may-fail=false -- -- """ -- ), -- }, - "yaml": textwrap.dedent( - """\ - version: 1 -@@ -1493,30 +1330,6 @@ NETWORK_CONFIGS = { - """ - ), - }, -- "expected_network_manager": { -- "cloud-init-iface0.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init iface0 -- uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 -- type=ethernet -- interface-name=iface0 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- -- [ipv6] -- method=dhcp -- may-fail=false -- addr-gen-mode=stable-privacy -- -- """ -- ), -- }, - }, - "dhcpv6_accept_ra": { - "expected_eni": textwrap.dedent( -@@ -1724,30 +1537,6 @@ NETWORK_CONFIGS = { - """ - ), - }, -- "expected_network_manager": { -- "cloud-init-iface0.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init iface0 -- uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 -- type=ethernet -- interface-name=iface0 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- -- [ipv6] -- method=auto -- may-fail=false -- addr-gen-mode=stable-privacy -- -- """ -- ), -- }, - }, - "static6": { - "yaml": textwrap.dedent( -@@ -1836,30 +1625,6 @@ NETWORK_CONFIGS = { - """ - ), - }, -- "expected_network_manager": { -- "cloud-init-iface0.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init iface0 -- uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 -- type=ethernet -- interface-name=iface0 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- -- [ipv6] -- method=auto -- may-fail=false -- addr-gen-mode=stable-privacy -- -- """ -- ), -- }, - }, - "dhcpv6_stateful": { - "expected_eni": textwrap.dedent( -@@ -1959,29 +1724,6 @@ NETWORK_CONFIGS = { +@@ -1959,29 +1883,6 @@ NETWORK_CONFIGS = { """ ), }, @@ -947,7 +756,7 @@ index ef21ad76..591241b3 100644 "yaml_v2": textwrap.dedent( """\ version: 2 -@@ -2035,30 +1777,6 @@ NETWORK_CONFIGS = { +@@ -2035,30 +1936,6 @@ NETWORK_CONFIGS = { """ ), }, @@ -978,304 +787,7 @@ index ef21ad76..591241b3 100644 "yaml_v2": textwrap.dedent( """\ version: 2 -@@ -2497,254 +2215,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true - USERCTL=no""" - ), - }, -- "expected_network_manager": { -- "cloud-init-eth3.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init eth3 -- uuid=b7e95dda-7746-5bf8-bf33-6e5f3c926790 -- type=ethernet -- slave-type=bridge -- master=dee46ce4-af7a-5e7c-aa08-b25533ae9213 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- mac-address=66:BB:9F:2C:E8:80 -- -- """ -- ), -- "cloud-init-eth5.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init eth5 -- uuid=5fda13c7-9942-5e90-a41b-1d043bd725dc -- type=ethernet -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- mac-address=98:BB:9F:2C:E8:8A -- -- [ipv4] -- method=auto -- may-fail=false -- -- """ -- ), -- "cloud-init-ib0.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init ib0 -- uuid=11a1dda7-78b4-5529-beba-d9b5f549ad7b -- type=infiniband -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [infiniband] -- transport-mode=datagram -- mtu=9000 -- mac-address=A0:00:02:20:FE:80:00:00:00:00:00:00:EC:0D:9A:03:00:15:E2:C1 -- -- [ipv4] -- method=manual -- may-fail=false -- address1=192.168.200.7/24 -- -- """ -- ), -- "cloud-init-bond0.200.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init bond0.200 -- uuid=88984a9c-ff22-5233-9267-86315e0acaa7 -- type=vlan -- interface-name=bond0.200 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [vlan] -- id=200 -- parent=54317911-f840-516b-a10d-82cb4c1f075c -- -- [ipv4] -- method=auto -- may-fail=false -- -- """ -- ), -- "cloud-init-eth0.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init eth0 -- uuid=1dd9a779-d327-56e1-8454-c65e2556c12c -- type=ethernet -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- mac-address=C0:D6:9F:2C:E8:80 -- -- """ -- ), -- "cloud-init-eth4.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init eth4 -- uuid=e27e4959-fb50-5580-b9a4-2073554627b9 -- type=ethernet -- slave-type=bridge -- master=dee46ce4-af7a-5e7c-aa08-b25533ae9213 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- mac-address=98:BB:9F:2C:E8:80 -- -- """ -- ), -- "cloud-init-eth1.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init eth1 -- uuid=3c50eb47-7260-5a6d-801d-bd4f587d6b58 -- type=ethernet -- slave-type=bond -- master=54317911-f840-516b-a10d-82cb4c1f075c -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- mac-address=AA:D6:9F:2C:E8:80 -- -- """ -- ), -- "cloud-init-br0.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init br0 -- uuid=dee46ce4-af7a-5e7c-aa08-b25533ae9213 -- type=bridge -- interface-name=br0 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [bridge] -- stp=false -- priority=22 -- mac-address=BB:BB:BB:BB:BB:AA -- -- [ipv4] -- method=manual -- may-fail=false -- address1=192.168.14.2/24 -- -- [ipv6] -- method=manual -- may-fail=false -- addr-gen-mode=stable-privacy -- address1=2001:1::1/64 -- route1=::/0,2001:4800:78ff:1b::1 -- -- """ -- ), -- "cloud-init-eth0.101.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init eth0.101 -- uuid=b5acec5e-db80-5935-8b02-0d5619fc42bf -- type=vlan -- interface-name=eth0.101 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [vlan] -- id=101 -- parent=1dd9a779-d327-56e1-8454-c65e2556c12c -- -- [ipv4] -- method=manual -- may-fail=false -- address1=192.168.0.2/24 -- gateway=192.168.0.1 -- dns=192.168.0.10;10.23.23.134; -- dns-search=barley.maas;sacchromyces.maas;brettanomyces.maas; -- address2=192.168.2.10/24 -- -- """ -- ), -- "cloud-init-bond0.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init bond0 -- uuid=54317911-f840-516b-a10d-82cb4c1f075c -- type=bond -- interface-name=bond0 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [bond] -- mode=active-backup -- miimon=100 -- xmit_hash_policy=layer3+4 -- -- [ipv6] -- method=dhcp -- may-fail=false -- addr-gen-mode=stable-privacy -- -- """ -- ), -- "cloud-init-eth2.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init eth2 -- uuid=5559a242-3421-5fdd-896e-9cb8313d5804 -- type=ethernet -- slave-type=bond -- master=54317911-f840-516b-a10d-82cb4c1f075c -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- mac-address=C0:BB:9F:2C:E8:80 -- -- """ -- ), -- }, - "yaml": textwrap.dedent( - """ - version: 1 -@@ -2933,10 +2403,10 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true - - type: static - address: 2001:1::1/92 - routes: -- - gateway: 2001:67c:1562::1 -+ - gateway: 2001:67c:1562:1 - network: 2001:67c:1 - netmask: "ffff:ffff::" -- - gateway: 3001:67c:15::1 -+ - gateway: 3001:67c:1562:1 - network: 3001:67c:1 - netmask: "ffff:ffff::" - metric: 10000 -@@ -2981,10 +2451,10 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true - - to: 10.1.3.0/24 - via: 192.168.0.3 - - to: 2001:67c:1/32 -- via: 2001:67c:1562::1 -+ via: 2001:67c:1562:1 - - metric: 10000 - to: 3001:67c:1/32 -- via: 3001:67c:15::1 -+ via: 3001:67c:1562:1 - """ - ), - "expected_eni": textwrap.dedent( -@@ -3044,11 +2514,11 @@ iface bond0 inet static - # control-alias bond0 - iface bond0 inet6 static - address 2001:1::1/92 -- post-up route add -A inet6 2001:67c:1/32 gw 2001:67c:1562::1 || true -- pre-down route del -A inet6 2001:67c:1/32 gw 2001:67c:1562::1 || true -- post-up route add -A inet6 3001:67c:1/32 gw 3001:67c:15::1 metric 10000 \ -+ post-up route add -A inet6 2001:67c:1/32 gw 2001:67c:1562:1 || true -+ pre-down route del -A inet6 2001:67c:1/32 gw 2001:67c:1562:1 || true -+ post-up route add -A inet6 3001:67c:1/32 gw 3001:67c:1562:1 metric 10000 \ - || true -- pre-down route del -A inet6 3001:67c:1/32 gw 3001:67c:15::1 metric 10000 \ -+ pre-down route del -A inet6 3001:67c:1/32 gw 3001:67c:1562:1 metric 10000 \ - || true - """ - ), -@@ -3091,8 +2561,8 @@ iface bond0 inet6 static +@@ -3092,8 +2969,8 @@ iface bond0 inet6 static - to: 2001:67c:1562:8007::1/64 via: 2001:67c:1562:8007::aac:40b2 - metric: 10000 @@ -1286,7 +798,7 @@ index ef21ad76..591241b3 100644 """ ), "expected_netplan-v2": textwrap.dedent( -@@ -3124,8 +2594,8 @@ iface bond0 inet6 static +@@ -3125,8 +3002,8 @@ iface bond0 inet6 static - to: 2001:67c:1562:8007::1/64 via: 2001:67c:1562:8007::aac:40b2 - metric: 10000 @@ -1297,249 +809,7 @@ index ef21ad76..591241b3 100644 ethernets: eth0: match: -@@ -3224,8 +2694,8 @@ iface bond0 inet6 static - """\ - # Created by cloud-init on instance boot automatically, do not edit. - # -- 2001:67c:1/32 via 2001:67c:1562::1 dev bond0 -- 3001:67c:1/32 via 3001:67c:15::1 metric 10000 dev bond0 -+ 2001:67c:1/32 via 2001:67c:1562:1 dev bond0 -+ 3001:67c:1/32 via 3001:67c:1562:1 metric 10000 dev bond0 - """ - ), - "route-bond0": textwrap.dedent( -@@ -3248,88 +2718,6 @@ iface bond0 inet6 static - """ - ), - }, -- "expected_network_manager": { -- "cloud-init-bond0s0.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init bond0s0 -- uuid=09d0b5b9-67e7-5577-a1af-74d1cf17a71e -- type=ethernet -- slave-type=bond -- master=54317911-f840-516b-a10d-82cb4c1f075c -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- mac-address=AA:BB:CC:DD:E8:00 -- -- """ -- ), -- "cloud-init-bond0s1.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init bond0s1 -- uuid=4d9aca96-b515-5630-ad83-d13daac7f9d0 -- type=ethernet -- slave-type=bond -- master=54317911-f840-516b-a10d-82cb4c1f075c -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- mac-address=AA:BB:CC:DD:E8:01 -- -- """ -- ), -- "cloud-init-bond0.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init bond0 -- uuid=54317911-f840-516b-a10d-82cb4c1f075c -- type=bond -- interface-name=bond0 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [bond] -- mode=active-backup -- miimon=100 -- xmit_hash_policy=layer3+4 -- num_grat_arp=5 -- downdelay=10 -- updelay=20 -- fail_over_mac=active -- primary_reselect=always -- primary=bond0s0 -- -- [ipv4] -- method=manual -- may-fail=false -- address1=192.168.0.2/24 -- gateway=192.168.0.1 -- route1=10.1.3.0/24,192.168.0.3 -- address2=192.168.1.2/24 -- -- [ipv6] -- method=manual -- may-fail=false -- addr-gen-mode=stable-privacy -- address1=2001:1::1/92 -- route1=2001:67c:1/32,2001:67c:1562::1 -- route2=3001:67c:1/32,3001:67c:15::1 -- -- """ -- ), -- }, - }, - "vlan": { - "yaml": textwrap.dedent( -@@ -3413,58 +2801,6 @@ iface bond0 inet6 static - VLAN=yes""" - ), - }, -- "expected_network_manager": { -- "cloud-init-en0.99.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init en0.99 -- uuid=f594e2ed-f107-51df-b225-1dc530a5356b -- type=vlan -- interface-name=en0.99 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [vlan] -- id=99 -- parent=e0ca478b-8d84-52ab-8fae-628482c629b5 -- -- [ipv4] -- method=manual -- may-fail=false -- address1=192.168.2.2/24 -- address2=192.168.1.2/24 -- gateway=192.168.1.1 -- -- [ipv6] -- method=manual -- may-fail=false -- addr-gen-mode=stable-privacy -- address1=2001:1::bbbb/96 -- route1=::/0,2001:1::1 -- -- """ -- ), -- "cloud-init-en0.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init en0 -- uuid=e0ca478b-8d84-52ab-8fae-628482c629b5 -- type=ethernet -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- mac-address=AA:BB:CC:DD:E8:00 -- -- """ -- ), -- }, - }, - "bridge": { - "yaml": textwrap.dedent( -@@ -3573,82 +2909,6 @@ iface bond0 inet6 static - """ - ), - }, -- "expected_network_manager": { -- "cloud-init-br0.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init br0 -- uuid=dee46ce4-af7a-5e7c-aa08-b25533ae9213 -- type=bridge -- interface-name=br0 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [bridge] -- stp=false -- priority=22 -- -- [ipv4] -- method=manual -- may-fail=false -- address1=192.168.2.2/24 -- -- """ -- ), -- "cloud-init-eth0.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init eth0 -- uuid=1dd9a779-d327-56e1-8454-c65e2556c12c -- type=ethernet -- slave-type=bridge -- master=dee46ce4-af7a-5e7c-aa08-b25533ae9213 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- mac-address=52:54:00:12:34:00 -- -- [ipv6] -- method=manual -- may-fail=false -- addr-gen-mode=stable-privacy -- address1=2001:1::100/96 -- -- """ -- ), -- "cloud-init-eth1.nmconnection": textwrap.dedent( -- """\ -- # Generated by cloud-init. Changes will be lost. -- -- [connection] -- id=cloud-init eth1 -- uuid=3c50eb47-7260-5a6d-801d-bd4f587d6b58 -- type=ethernet -- slave-type=bridge -- master=dee46ce4-af7a-5e7c-aa08-b25533ae9213 -- -- [user] -- org.freedesktop.NetworkManager.origin=cloud-init -- -- [ethernet] -- mac-address=52:54:00:12:34:01 -- -- [ipv6] -- method=manual -- may-fail=false -- addr-gen-mode=stable-privacy -- address1=2001:1::101/96 -- -- """ -- ), -- }, - }, - "manual": { - "yaml": textwrap.dedent( -@@ -3777,92 +3037,25 @@ iface bond0 inet6 static +@@ -3774,73 +3651,6 @@ iface bond0 inet6 static """ ), }, @@ -1552,12 +822,10 @@ index ef21ad76..591241b3 100644 - id=cloud-init eth0 - uuid=1dd9a779-d327-56e1-8454-c65e2556c12c - type=ethernet -+ }, -+} - +- - [user] - org.freedesktop.NetworkManager.origin=cloud-init - +- - [ethernet] - mac-address=52:54:00:12:34:00 - @@ -1612,44 +880,10 @@ index ef21ad76..591241b3 100644 - """ - ), - }, -- }, --} -- -- --CONFIG_V1_EXPLICIT_LOOPBACK = { -- "version": 1, -- "config": [ -- { -- "name": "eth0", -- "type": "physical", -- "subnets": [{"control": "auto", "type": "dhcp"}], -- }, -- { -- "name": "lo", -- "type": "loopback", -- "subnets": [{"control": "auto", "type": "loopback"}], -- }, -- ], --} -+CONFIG_V1_EXPLICIT_LOOPBACK = { -+ "version": 1, -+ "config": [ -+ { -+ "name": "eth0", -+ "type": "physical", -+ "subnets": [{"control": "auto", "type": "dhcp"}], -+ }, -+ { -+ "name": "lo", -+ "type": "loopback", -+ "subnets": [{"control": "auto", "type": "loopback"}], -+ }, -+ ], -+} - - - CONFIG_V1_SIMPLE_SUBNET = { -@@ -4304,6 +3497,7 @@ class TestRhelSysConfigRendering(CiTestCase): + }, + "v2-dev-name-via-mac-lookup": { + "expected_sysconfig_rhel": { +@@ -4339,6 +4149,7 @@ class TestRhelSysConfigRendering(CiTestCase): with_logs = True @@ -1657,7 +891,7 @@ index ef21ad76..591241b3 100644 scripts_dir = "/etc/sysconfig/network-scripts" header = ( "# Created by cloud-init on instance boot automatically, " -@@ -4878,6 +4072,78 @@ USERCTL=no +@@ -4913,6 +4724,78 @@ USERCTL=no self._compare_files_to_expected(entry[self.expected_name], found) self._assert_headers(found) @@ -1736,7 +970,7 @@ index ef21ad76..591241b3 100644 def test_netplan_dhcp_false_disable_dhcp_in_state(self): """netplan config with dhcp[46]: False should not add dhcp in state""" net_config = yaml.load(NETPLAN_DHCP_FALSE) -@@ -5433,281 +4699,6 @@ STARTMODE=auto +@@ -5609,281 +5492,6 @@ STARTMODE=auto self._assert_headers(found) @@ -2018,7 +1252,7 @@ index ef21ad76..591241b3 100644 class TestEniNetRendering(CiTestCase): @mock.patch("cloudinit.net.util.get_cmdline", return_value="root=myroot") @mock.patch("cloudinit.net.sys_dev_path") -@@ -7145,9 +6136,9 @@ class TestNetworkdRoundTrip(CiTestCase): +@@ -7651,9 +7259,9 @@ class TestNetworkdRoundTrip(CiTestCase): class TestRenderersSelect: @pytest.mark.parametrize( @@ -2030,7 +1264,7 @@ index ef21ad76..591241b3 100644 ( net.RendererNotFoundError, False, -@@ -7155,51 +6146,52 @@ class TestRenderersSelect: +@@ -7661,51 +7269,52 @@ class TestRenderersSelect: False, False, False, @@ -2105,7 +1339,7 @@ index ef21ad76..591241b3 100644 m_networkd_avail.return_value = networkd # networkd presence if isinstance(renderer_selected, str): (renderer_name, _rnd_class) = renderers.select( -@@ -7257,7 +6249,7 @@ class TestNetRenderers(CiTestCase): +@@ -7763,7 +7372,7 @@ class TestNetRenderers(CiTestCase): priority=["sysconfig", "eni"], ) @@ -2115,35 +1349,10 @@ index ef21ad76..591241b3 100644 def test_sysconfig_available_uses_variant_mapping(self, m_info, m_avail): m_avail.return_value = True diff --git a/tests/unittests/test_net_activators.py b/tests/unittests/test_net_activators.py -index 4525c49c..3c29e2f7 100644 +index afd9056a..b735ea9e 100644 --- a/tests/unittests/test_net_activators.py +++ b/tests/unittests/test_net_activators.py -@@ -41,20 +41,18 @@ NETPLAN_CALL_LIST = [ - - @pytest.fixture - def available_mocks(): -- mocks = namedtuple("Mocks", "m_which, m_file, m_exists") -+ mocks = namedtuple("Mocks", "m_which, m_file") - with patch("cloudinit.subp.which", return_value=True) as m_which: - with patch("os.path.isfile", return_value=True) as m_file: -- with patch("os.path.exists", return_value=True) as m_exists: -- yield mocks(m_which, m_file, m_exists) -+ yield mocks(m_which, m_file) - - - @pytest.fixture - def unavailable_mocks(): -- mocks = namedtuple("Mocks", "m_which, m_file, m_exists") -+ mocks = namedtuple("Mocks", "m_which, m_file") - with patch("cloudinit.subp.which", return_value=False) as m_which: - with patch("os.path.isfile", return_value=False) as m_file: -- with patch("os.path.exists", return_value=False) as m_exists: -- yield mocks(m_which, m_file, m_exists) -+ yield mocks(m_which, m_file) - - - class TestSearchAndSelect: -@@ -115,6 +113,10 @@ NETPLAN_AVAILABLE_CALLS = [ +@@ -139,6 +139,10 @@ NETPLAN_AVAILABLE_CALLS = [ (("netplan",), {"search": ["/usr/sbin", "/sbin"], "target": None}), ] @@ -2154,7 +1363,7 @@ index 4525c49c..3c29e2f7 100644 NETWORKD_AVAILABLE_CALLS = [ (("ip",), {"search": ["/usr/sbin", "/bin"], "target": None}), (("systemctl",), {"search": ["/usr/sbin", "/bin"], "target": None}), -@@ -126,6 +128,7 @@ NETWORKD_AVAILABLE_CALLS = [ +@@ -150,6 +154,7 @@ NETWORKD_AVAILABLE_CALLS = [ [ (IfUpDownActivator, IF_UP_DOWN_AVAILABLE_CALLS), (NetplanActivator, NETPLAN_AVAILABLE_CALLS), @@ -2162,82 +1371,7 @@ index 4525c49c..3c29e2f7 100644 (NetworkdActivator, NETWORKD_AVAILABLE_CALLS), ], ) -@@ -141,72 +144,8 @@ IF_UP_DOWN_BRING_UP_CALL_LIST = [ - ] - - NETWORK_MANAGER_BRING_UP_CALL_LIST = [ -- ( -- ( -- [ -- "nmcli", -- "connection", -- "load", -- "".join( -- [ -- "/etc/NetworkManager/system-connections", -- "/cloud-init-eth0.nmconnection", -- ] -- ), -- ], -- ), -- {}, -- ), -- ( -- ( -- [ -- "nmcli", -- "connection", -- "up", -- "filename", -- "".join( -- [ -- "/etc/NetworkManager/system-connections", -- "/cloud-init-eth0.nmconnection", -- ] -- ), -- ], -- ), -- {}, -- ), -- ( -- ( -- [ -- "nmcli", -- "connection", -- "load", -- "".join( -- [ -- "/etc/NetworkManager/system-connections", -- "/cloud-init-eth1.nmconnection", -- ] -- ), -- ], -- ), -- {}, -- ), -- ( -- ( -- [ -- "nmcli", -- "connection", -- "up", -- "filename", -- "".join( -- [ -- "/etc/NetworkManager/system-connections", -- "/cloud-init-eth1.nmconnection", -- ] -- ), -- ], -- ), -- {}, -- ), -+ ((["nmcli", "connection", "up", "ifname", "eth0"],), {}), -+ ((["nmcli", "connection", "up", "ifname", "eth1"],), {}), - ] - - NETWORKD_BRING_UP_CALL_LIST = [ -@@ -230,11 +169,9 @@ class TestActivatorsBringUp: +@@ -254,11 +259,9 @@ class TestActivatorsBringUp: def test_bring_up_interface( self, m_subp, activator, expected_call_list, available_mocks ): @@ -2251,17 +1385,3 @@ index 4525c49c..3c29e2f7 100644 @patch("cloudinit.subp.subp", return_value=("", "")) def test_bring_up_interfaces( -@@ -271,8 +208,8 @@ IF_UP_DOWN_BRING_DOWN_CALL_LIST = [ - ] - - NETWORK_MANAGER_BRING_DOWN_CALL_LIST = [ -- ((["nmcli", "device", "disconnect", "eth0"],), {}), -- ((["nmcli", "device", "disconnect", "eth1"],), {}), -+ ((["nmcli", "connection", "down", "eth0"],), {}), -+ ((["nmcli", "connection", "down", "eth1"],), {}), - ] - - NETWORKD_BRING_DOWN_CALL_LIST = [ --- -2.31.1 - diff --git a/SOURCES/0006-rhel-cloud.cfg-remove-ssh_genkeytypes-in-settings.py.patch b/SOURCES/0006-rhel-cloud.cfg-remove-ssh_genkeytypes-in-settings.py.patch deleted file mode 100644 index fb05778..0000000 --- a/SOURCES/0006-rhel-cloud.cfg-remove-ssh_genkeytypes-in-settings.py.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 00f1f910d8d166ebe2913c12549f212c2d666c11 Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Thu, 20 May 2021 08:53:55 +0200 -Subject: rhel/cloud.cfg: remove ssh_genkeytypes in settings.py and set in - cloud.cfg - -RH-Author: Emanuele Giuseppe Esposito -RH-MergeRequest: 10: rhel/cloud.cfg: remove ssh_genkeytypes in settings.py and set in cloud.cfg -RH-Commit: [1/1] 6da989423b9b6e017afbac2f1af3649b0487310f -RH-Bugzilla: 1957532 -RH-Acked-by: Eduardo Otubo -RH-Acked-by: Cathy Avery -RH-Acked-by: Vitaly Kuznetsov -RH-Acked-by: Mohamed Gamal Morsy - -Currently genkeytypes in cloud.cfg is set to None, so together with -ssh_deletekeys=1 cloudinit on first boot it will just delete the existing -keys and not generate new ones. - -Just removing that property in cloud.cfg is not enough, because -settings.py provides another empty default value that will be used -instead, resulting to no key generated even when the property is not defined. - -Removing genkeytypes also in settings.py will default to GENERATE_KEY_NAMES, -but since we want only 'rsa', 'ecdsa' and 'ed25519', add back genkeytypes in -cloud.cfg with the above defaults. - -Also remove ssh_deletekeys in settings.py as we always need -to 1 (and it also defaults to 1). - -Signed-off-by: Emanuele Giuseppe Esposito ---- - cloudinit/settings.py | 2 -- - rhel/cloud.cfg | 2 +- - 2 files changed, 1 insertion(+), 3 deletions(-) - -diff --git a/cloudinit/settings.py b/cloudinit/settings.py -index aa2d6b95..38a90b70 100644 ---- a/cloudinit/settings.py -+++ b/cloudinit/settings.py -@@ -52,8 +52,6 @@ CFG_BUILTIN = { - 'def_log_file_mode': 0o600, - 'log_cfgs': [], - 'mount_default_fields': [None, None, 'auto', 'defaults,nofail', '0', '2'], -- 'ssh_deletekeys': False, -- 'ssh_genkeytypes': [], - 'syslog_fix_perms': [], - 'system_info': { - 'paths': { -diff --git a/rhel/cloud.cfg b/rhel/cloud.cfg -index 1ec1a6c6..75d5c84b 100644 ---- a/rhel/cloud.cfg -+++ b/rhel/cloud.cfg -@@ -7,7 +7,7 @@ ssh_pwauth: 0 - mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service,_netdev', '0', '2'] - resize_rootfs_tmp: /dev - ssh_deletekeys: 1 --ssh_genkeytypes: ~ -+ssh_genkeytypes: ['rsa', 'ecdsa', 'ed25519'] - syslog_fix_perms: ~ - disable_vmware_customization: false - --- -2.31.1 - diff --git a/SOURCES/0007-rhel-make-sure-previous-hostname-file-ends-with-a-ne.patch b/SOURCES/0007-rhel-make-sure-previous-hostname-file-ends-with-a-ne.patch new file mode 100644 index 0000000..7422b7e --- /dev/null +++ b/SOURCES/0007-rhel-make-sure-previous-hostname-file-ends-with-a-ne.patch @@ -0,0 +1,54 @@ +From ac0cf308318d423162ce3b7be32dcbf88f20ff50 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Tue, 4 Apr 2023 19:59:07 +0530 +Subject: [PATCH] rhel: make sure previous-hostname file ends with a new line + (#2108) + +cloud-init strips new line from "/etc/hostname" on rhel distro when processing +"/var/lib/cloud/data/previous-hostname". Although this does not pose a serious +issue, it is still better if the behavior is similar to other distros like +Ubuntu where /previous-hostname does end with a new line. Fix this issue by +using hostname parser in rhel similar to debian. + +Signed-off-by: Ani Sinha +(cherry picked from commit 6d42aa8e2c1a5454a658ab4e2b9cead2677c77cd) +--- + cloudinit/distros/rhel.py | 5 ++++- + tools/.github-cla-signers | 1 + + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/cloudinit/distros/rhel.py b/cloudinit/distros/rhel.py +index df7dc3d6..9625709e 100644 +--- a/cloudinit/distros/rhel.py ++++ b/cloudinit/distros/rhel.py +@@ -13,6 +13,7 @@ from cloudinit import distros, helpers + from cloudinit import log as logging + from cloudinit import subp, util + from cloudinit.distros import rhel_util ++from cloudinit.distros.parsers.hostname import HostnameConf + from cloudinit.settings import PER_INSTANCE + + LOG = logging.getLogger(__name__) +@@ -111,7 +112,9 @@ class Distro(distros.Distro): + # systemd will never update previous-hostname for us, so + # we need to do it ourselves + if self.uses_systemd() and filename.endswith("/previous-hostname"): +- util.write_file(filename, hostname) ++ conf = HostnameConf("") ++ conf.set_hostname(hostname) ++ util.write_file(filename, str(conf), 0o644) + elif self.uses_systemd(): + subp.subp(["hostnamectl", "set-hostname", str(hostname)]) + else: +diff --git a/tools/.github-cla-signers b/tools/.github-cla-signers +index d8cca015..457dacf4 100644 +--- a/tools/.github-cla-signers ++++ b/tools/.github-cla-signers +@@ -9,6 +9,7 @@ andgein + andrew-lee-metaswitch + andrewbogott + andrewlukoshko ++ani-sinha + antonyc + aswinrajamannar + beantaxi diff --git a/SOURCES/0008-Don-t-change-permissions-of-netrules-target-2076.patch b/SOURCES/0008-Don-t-change-permissions-of-netrules-target-2076.patch new file mode 100644 index 0000000..d9bdf4f --- /dev/null +++ b/SOURCES/0008-Don-t-change-permissions-of-netrules-target-2076.patch @@ -0,0 +1,121 @@ +From 34ef256dc614c7dcf5b04a431d410030e333d82b Mon Sep 17 00:00:00 2001 +From: Emanuele Giuseppe Esposito +Date: Mon, 17 Apr 2023 10:20:16 +0200 +Subject: [PATCH] Don't change permissions of netrules target (#2076) + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2182948 + +commit 56c88cafd1b3606e814069a79f4ec265fc427c87 +Author: James Falcon +Date: Thu Mar 23 10:21:56 2023 -0500 + + Don't change permissions of netrules target (#2076) + + Set permissions if file doesn't exist. Leave them if it does. + + LP: #2011783 + + Co-authored-by: Chad Smith + + Conflicts: + cloudinit/net/sysconfig.py: enable_ifcfg_rh missing upstream + +Signed-off-by: Emanuele Giuseppe Esposito +--- + cloudinit/net/eni.py | 4 +++- + cloudinit/net/sysconfig.py | 7 ++++++- + tests/unittests/distros/test_netconfig.py | 20 ++++++++++++++++++-- + 3 files changed, 27 insertions(+), 4 deletions(-) + +diff --git a/cloudinit/net/eni.py b/cloudinit/net/eni.py +index 53bd35ca..1de3bec2 100644 +--- a/cloudinit/net/eni.py ++++ b/cloudinit/net/eni.py +@@ -576,7 +576,9 @@ class Renderer(renderer.Renderer): + netrules = subp.target_path(target, self.netrules_path) + util.ensure_dir(os.path.dirname(netrules)) + util.write_file( +- netrules, self._render_persistent_net(network_state) ++ netrules, ++ content=self._render_persistent_net(network_state), ++ preserve_mode=True, + ) + + +diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py +index 765c248a..e08c0c69 100644 +--- a/cloudinit/net/sysconfig.py ++++ b/cloudinit/net/sysconfig.py +@@ -1034,7 +1034,12 @@ class Renderer(renderer.Renderer): + if self.netrules_path: + netrules_content = self._render_persistent_net(network_state) + netrules_path = subp.target_path(target, self.netrules_path) +- util.write_file(netrules_path, netrules_content, file_mode) ++ util.write_file( ++ netrules_path, ++ content=netrules_content, ++ mode=file_mode, ++ preserve_mode=True, ++ ) + if available_nm(target=target): + enable_ifcfg_rh(subp.target_path(target, path=NM_CFG_FILE)) + +diff --git a/tests/unittests/distros/test_netconfig.py b/tests/unittests/distros/test_netconfig.py +index e9fb0591..b1c89ce3 100644 +--- a/tests/unittests/distros/test_netconfig.py ++++ b/tests/unittests/distros/test_netconfig.py +@@ -458,8 +458,16 @@ class TestNetCfgDistroUbuntuEni(TestNetCfgDistroBase): + def eni_path(self): + return "/etc/network/interfaces.d/50-cloud-init.cfg" + ++ def rules_path(self): ++ return "/etc/udev/rules.d/70-persistent-net.rules" ++ + def _apply_and_verify_eni( +- self, apply_fn, config, expected_cfgs=None, bringup=False ++ self, ++ apply_fn, ++ config, ++ expected_cfgs=None, ++ bringup=False, ++ previous_files=(), + ): + if not expected_cfgs: + raise ValueError("expected_cfg must not be None") +@@ -467,7 +475,11 @@ class TestNetCfgDistroUbuntuEni(TestNetCfgDistroBase): + tmpd = None + with mock.patch("cloudinit.net.eni.available") as m_avail: + m_avail.return_value = True ++ path_modes = {} + with self.reRooted(tmpd) as tmpd: ++ for previous_path, content, mode in previous_files: ++ util.write_file(previous_path, content, mode=mode) ++ path_modes[previous_path] = mode + apply_fn(config, bringup) + + results = dir2dict(tmpd) +@@ -478,7 +490,9 @@ class TestNetCfgDistroUbuntuEni(TestNetCfgDistroBase): + print(results[cfgpath]) + print("----------") + self.assertEqual(expected, results[cfgpath]) +- self.assertEqual(0o644, get_mode(cfgpath, tmpd)) ++ self.assertEqual( ++ path_modes.get(cfgpath, 0o644), get_mode(cfgpath, tmpd) ++ ) + + def test_apply_network_config_and_bringup_filters_priority_eni_ub(self): + """Network activator search priority can be overridden from config.""" +@@ -527,11 +541,13 @@ class TestNetCfgDistroUbuntuEni(TestNetCfgDistroBase): + def test_apply_network_config_eni_ub(self): + expected_cfgs = { + self.eni_path(): V1_NET_CFG_OUTPUT, ++ self.rules_path(): "", + } + self._apply_and_verify_eni( + self.distro.apply_network_config, + V1_NET_CFG, + expected_cfgs=expected_cfgs.copy(), ++ previous_files=((self.rules_path(), "something", 0o660),), + ) + + def test_apply_network_config_ipv6_ub(self): diff --git a/SOURCES/0009-Make-user-vendor-data-sensitive-and-remove-log-permi.patch b/SOURCES/0009-Make-user-vendor-data-sensitive-and-remove-log-permi.patch new file mode 100644 index 0000000..570a42b --- /dev/null +++ b/SOURCES/0009-Make-user-vendor-data-sensitive-and-remove-log-permi.patch @@ -0,0 +1,295 @@ +From d092efe0f437ad149f6d6e3a9f8b816c0f5c1c2a Mon Sep 17 00:00:00 2001 +From: James Falcon +Date: Wed, 26 Apr 2023 15:11:55 -0500 +Subject: [PATCH] Make user/vendor data sensitive and remove log permissions + (#2144) + +Because user data and vendor data may contain sensitive information, +this commit ensures that any user data or vendor data written to +instance-data.json gets redacted and is only available to root user. + +Also, modify the permissions of cloud-init.log to be 640, so that +sensitive data leaked to the log isn't world readable. +Additionally, remove the logging of user data and vendor data to +cloud-init.log from the Vultr datasource. + +LP: #2013967 +CVE: CVE-2023-1786 +(cherry picked from commit a378b7e4f47375458651c0972e7cd813f6fe0a6b) +Signed-off-by: Ani Sinha +--- + cloudinit/sources/DataSourceLXD.py | 9 ++++++--- + cloudinit/sources/DataSourceVultr.py | 14 ++++++-------- + cloudinit/sources/__init__.py | 28 +++++++++++++++++++++++++--- + cloudinit/stages.py | 4 +++- + tests/unittests/sources/test_init.py | 27 ++++++++++++++++++++++++++- + tests/unittests/test_stages.py | 18 +++++++++++------- + 6 files changed, 77 insertions(+), 23 deletions(-) + +diff --git a/cloudinit/sources/DataSourceLXD.py b/cloudinit/sources/DataSourceLXD.py +index ab440cc8..e4cae91a 100644 +--- a/cloudinit/sources/DataSourceLXD.py ++++ b/cloudinit/sources/DataSourceLXD.py +@@ -14,7 +14,7 @@ import stat + import time + from enum import Flag, auto + from json.decoder import JSONDecodeError +-from typing import Any, Dict, List, Optional, Union, cast ++from typing import Any, Dict, List, Optional, Tuple, Union, cast + + import requests + from requests.adapters import HTTPAdapter +@@ -168,11 +168,14 @@ class DataSourceLXD(sources.DataSource): + _network_config: Union[Dict, str] = sources.UNSET + _crawled_metadata: Union[Dict, str] = sources.UNSET + +- sensitive_metadata_keys = ( +- "merged_cfg", ++ sensitive_metadata_keys: Tuple[ ++ str, ... ++ ] = sources.DataSource.sensitive_metadata_keys + ( + "user.meta-data", + "user.vendor-data", + "user.user-data", ++ "cloud-init.user-data", ++ "cloud-init.vendor-data", + ) + + skip_hotplug_detect = True +diff --git a/cloudinit/sources/DataSourceVultr.py b/cloudinit/sources/DataSourceVultr.py +index 9d7c84fb..660e9f14 100644 +--- a/cloudinit/sources/DataSourceVultr.py ++++ b/cloudinit/sources/DataSourceVultr.py +@@ -5,6 +5,8 @@ + # Vultr Metadata API: + # https://www.vultr.com/metadata/ + ++from typing import Tuple ++ + import cloudinit.sources.helpers.vultr as vultr + from cloudinit import log as log + from cloudinit import sources, util, version +@@ -28,6 +30,10 @@ class DataSourceVultr(sources.DataSource): + + dsname = "Vultr" + ++ sensitive_metadata_keys: Tuple[ ++ str, ... ++ ] = sources.DataSource.sensitive_metadata_keys + ("startup-script",) ++ + def __init__(self, sys_cfg, distro, paths): + super(DataSourceVultr, self).__init__(sys_cfg, distro, paths) + self.ds_cfg = util.mergemanydict( +@@ -54,13 +60,8 @@ class DataSourceVultr(sources.DataSource): + self.get_datasource_data(self.metadata) + + # Dump some data so diagnosing failures is manageable +- LOG.debug("Vultr Vendor Config:") +- LOG.debug(util.json_dumps(self.metadata["vendor-data"])) + LOG.debug("SUBID: %s", self.metadata["instance-id"]) + LOG.debug("Hostname: %s", self.metadata["local-hostname"]) +- if self.userdata_raw is not None: +- LOG.debug("User-Data:") +- LOG.debug(self.userdata_raw) + + return True + +@@ -146,7 +147,4 @@ if __name__ == "__main__": + config = md["vendor-data"] + sysinfo = vultr.get_sysinfo() + +- print(util.json_dumps(sysinfo)) +- print(util.json_dumps(config)) +- + # vi: ts=4 expandtab +diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py +index 565e1754..5c6ae8b1 100644 +--- a/cloudinit/sources/__init__.py ++++ b/cloudinit/sources/__init__.py +@@ -110,7 +110,10 @@ def process_instance_metadata(metadata, key_path="", sensitive_keys=()): + sub_key_path = key_path + "/" + key + else: + sub_key_path = key +- if key in sensitive_keys or sub_key_path in sensitive_keys: ++ if ( ++ key.lower() in sensitive_keys ++ or sub_key_path.lower() in sensitive_keys ++ ): + sens_keys.append(sub_key_path) + if isinstance(val, str) and val.startswith("ci-b64:"): + base64_encoded_keys.append(sub_key_path) +@@ -132,6 +135,12 @@ def redact_sensitive_keys(metadata, redact_value=REDACT_SENSITIVE_VALUE): + + Replace any keys values listed in 'sensitive_keys' with redact_value. + """ ++ # While 'sensitive_keys' should already sanitized to only include what ++ # is in metadata, it is possible keys will overlap. For example, if ++ # "merged_cfg" and "merged_cfg/ds/userdata" both match, it's possible that ++ # "merged_cfg" will get replaced first, meaning "merged_cfg/ds/userdata" ++ # no longer represents a valid key. ++ # Thus, we still need to do membership checks in this function. + if not metadata.get("sensitive_keys", []): + return metadata + md_copy = copy.deepcopy(metadata) +@@ -139,9 +148,14 @@ def redact_sensitive_keys(metadata, redact_value=REDACT_SENSITIVE_VALUE): + path_parts = key_path.split("/") + obj = md_copy + for path in path_parts: +- if isinstance(obj[path], dict) and path != path_parts[-1]: ++ if ( ++ path in obj ++ and isinstance(obj[path], dict) ++ and path != path_parts[-1] ++ ): + obj = obj[path] +- obj[path] = redact_value ++ if path in obj: ++ obj[path] = redact_value + return md_copy + + +@@ -249,6 +263,14 @@ class DataSource(CloudInitPickleMixin, metaclass=abc.ABCMeta): + sensitive_metadata_keys: Tuple[str, ...] = ( + "merged_cfg", + "security-credentials", ++ "userdata", ++ "user-data", ++ "user_data", ++ "vendordata", ++ "vendor-data", ++ # Provide ds/vendor_data to avoid redacting top-level ++ # "vendor_data": {enabled: True} ++ "ds/vendor_data", + ) + + # True on datasources that may not see hotplugged devices reflected +diff --git a/cloudinit/stages.py b/cloudinit/stages.py +index a624a6fb..1326d205 100644 +--- a/cloudinit/stages.py ++++ b/cloudinit/stages.py +@@ -204,7 +204,9 @@ class Init: + log_file = util.get_cfg_option_str(self.cfg, "def_log_file") + log_file_mode = util.get_cfg_option_int(self.cfg, "def_log_file_mode") + if log_file: +- util.ensure_file(log_file, mode=0o640, preserve_mode=True) ++ # At this point the log file should have already been created ++ # in the setupLogging function of log.py ++ util.ensure_file(log_file, mode=0o640, preserve_mode=False) + perms = self.cfg.get("syslog_fix_perms") + if not perms: + perms = {} +diff --git a/tests/unittests/sources/test_init.py b/tests/unittests/sources/test_init.py +index 0447e02c..eb27198f 100644 +--- a/tests/unittests/sources/test_init.py ++++ b/tests/unittests/sources/test_init.py +@@ -458,12 +458,24 @@ class TestDataSource(CiTestCase): + "cred2": "othersekret", + } + }, ++ "someother": { ++ "nested": { ++ "userData": "HIDE ME", ++ } ++ }, ++ "VENDOR-DAta": "HIDE ME TOO", + }, + ) + self.assertCountEqual( + ( + "merged_cfg", + "security-credentials", ++ "userdata", ++ "user-data", ++ "user_data", ++ "vendordata", ++ "vendor-data", ++ "ds/vendor_data", + ), + datasource.sensitive_metadata_keys, + ) +@@ -490,7 +502,9 @@ class TestDataSource(CiTestCase): + "base64_encoded_keys": [], + "merged_cfg": REDACT_SENSITIVE_VALUE, + "sensitive_keys": [ ++ "ds/meta_data/VENDOR-DAta", + "ds/meta_data/some/security-credentials", ++ "ds/meta_data/someother/nested/userData", + "merged_cfg", + ], + "sys_info": sys_info, +@@ -500,6 +514,7 @@ class TestDataSource(CiTestCase): + "availability_zone": "myaz", + "cloud-name": "subclasscloudname", + "cloud_name": "subclasscloudname", ++ "cloud_id": "subclasscloudname", + "distro": "ubuntu", + "distro_release": "focal", + "distro_version": "20.04", +@@ -522,14 +537,18 @@ class TestDataSource(CiTestCase): + "ds": { + "_doc": EXPERIMENTAL_TEXT, + "meta_data": { ++ "VENDOR-DAta": REDACT_SENSITIVE_VALUE, + "availability_zone": "myaz", + "local-hostname": "test-subclass-hostname", + "region": "myregion", + "some": {"security-credentials": REDACT_SENSITIVE_VALUE}, ++ "someother": { ++ "nested": {"userData": REDACT_SENSITIVE_VALUE} ++ }, + }, + }, + } +- self.assertCountEqual(expected, redacted) ++ self.assertEqual(expected, redacted) + file_stat = os.stat(json_file) + self.assertEqual(0o644, stat.S_IMODE(file_stat.st_mode)) + +@@ -574,6 +593,12 @@ class TestDataSource(CiTestCase): + ( + "merged_cfg", + "security-credentials", ++ "userdata", ++ "user-data", ++ "user_data", ++ "vendordata", ++ "vendor-data", ++ "ds/vendor_data", + ), + datasource.sensitive_metadata_keys, + ) +diff --git a/tests/unittests/test_stages.py b/tests/unittests/test_stages.py +index 15a7e973..a61f9df9 100644 +--- a/tests/unittests/test_stages.py ++++ b/tests/unittests/test_stages.py +@@ -606,19 +606,23 @@ class TestInit_InitializeFilesystem: + # Assert we create it 0o640 by default if it doesn't already exist + assert 0o640 == stat.S_IMODE(log_file.stat().mode) + +- def test_existing_file_permissions_are_not_modified(self, init, tmpdir): +- """If the log file already exists, we should not modify its permissions ++ def test_existing_file_permissions(self, init, tmpdir): ++ """Test file permissions are set as expected. ++ ++ CIS Hardening requires 640 permissions. These permissions are ++ currently hardcoded on every boot, but if there's ever a reason ++ to change this, we need to then ensure that they ++ are *not* set every boot. + + See https://bugs.launchpad.net/cloud-init/+bug/1900837. + """ +- # Use a mode that will never be made the default so this test will +- # always be valid +- mode = 0o606 + log_file = tmpdir.join("cloud-init.log") + log_file.ensure() +- log_file.chmod(mode) ++ # Use a mode that will never be made the default so this test will ++ # always be valid ++ log_file.chmod(0o606) + init._cfg = {"def_log_file": str(log_file)} + + init._initialize_filesystem() + +- assert mode == stat.S_IMODE(log_file.stat().mode) ++ assert 0o640 == stat.S_IMODE(log_file.stat().mode) diff --git a/SOURCES/0010-Do-not-generate-dsa-and-ed25519-key-types-when-crypt.patch b/SOURCES/0010-Do-not-generate-dsa-and-ed25519-key-types-when-crypt.patch new file mode 100644 index 0000000..d51a9dd --- /dev/null +++ b/SOURCES/0010-Do-not-generate-dsa-and-ed25519-key-types-when-crypt.patch @@ -0,0 +1,206 @@ +From 6bf6ceab79df97eb1c90b4df61f654bc0b2f598c Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Tue, 2 May 2023 20:35:45 +0530 +Subject: [PATCH] Do not generate dsa and ed25519 key types when crypto FIPS + mode is enabled (#2142) + +DSA and ED25519 key types are not supported when FIPS is enabled in crypto. +Check if FIPS has been enabled on the system and if so, do not generate those +key types. Presently the check is only available on Linux systems. + +LP: 2017761 +RHBZ: 2187164 + +Signed-off-by: Ani Sinha +(cherry picked from commit c53f04aeb2acf9526a2ebf3d3320f149ac46caa6) +--- + cloudinit/config/cc_ssh.py | 21 +++++++++++++++- + cloudinit/util.py | 12 +++++++++ + tests/unittests/config/test_cc_ssh.py | 36 +++++++++++++++++++++------ + tests/unittests/test_util.py | 25 +++++++++++++++++++ + 4 files changed, 85 insertions(+), 9 deletions(-) + +diff --git a/cloudinit/config/cc_ssh.py b/cloudinit/config/cc_ssh.py +index 1ec889f3..5578654a 100644 +--- a/cloudinit/config/cc_ssh.py ++++ b/cloudinit/config/cc_ssh.py +@@ -172,6 +172,8 @@ meta: MetaSchema = { + __doc__ = get_meta_doc(meta) + + GENERATE_KEY_NAMES = ["rsa", "dsa", "ecdsa", "ed25519"] ++FIPS_UNSUPPORTED_KEY_NAMES = ["dsa", "ed25519"] ++ + pattern_unsupported_config_keys = re.compile( + "^(ecdsa-sk|ed25519-sk)_(private|public|certificate)$" + ) +@@ -259,9 +261,26 @@ def handle( + genkeys = util.get_cfg_option_list( + cfg, "ssh_genkeytypes", GENERATE_KEY_NAMES + ) ++ # remove keys that are not supported in fips mode if its enabled ++ key_names = ( ++ genkeys ++ if not util.fips_enabled() ++ else [ ++ names ++ for names in genkeys ++ if names not in FIPS_UNSUPPORTED_KEY_NAMES ++ ] ++ ) ++ skipped_keys = set(genkeys).difference(key_names) ++ if skipped_keys: ++ log.debug( ++ "skipping keys that are not supported in fips mode: %s", ++ ",".join(skipped_keys), ++ ) ++ + lang_c = os.environ.copy() + lang_c["LANG"] = "C" +- for keytype in genkeys: ++ for keytype in key_names: + keyfile = KEY_FILE_TPL % (keytype) + if os.path.exists(keyfile): + continue +diff --git a/cloudinit/util.py b/cloudinit/util.py +index 8ba3e2b6..4a8e3d3b 100644 +--- a/cloudinit/util.py ++++ b/cloudinit/util.py +@@ -1577,6 +1577,18 @@ def get_cmdline(): + return _get_cmdline() + + ++def fips_enabled() -> bool: ++ fips_proc = "/proc/sys/crypto/fips_enabled" ++ try: ++ contents = load_file(fips_proc).strip() ++ return contents == "1" ++ except (IOError, OSError): ++ # for BSD systems and Linux systems where the proc entry is not ++ # available, we assume FIPS is disabled to retain the old behavior ++ # for now. ++ return False ++ ++ + def pipe_in_out(in_fh, out_fh, chunk_size=1024, chunk_cb=None): + bytes_piped = 0 + while True: +diff --git a/tests/unittests/config/test_cc_ssh.py b/tests/unittests/config/test_cc_ssh.py +index 66368d0f..72941a95 100644 +--- a/tests/unittests/config/test_cc_ssh.py ++++ b/tests/unittests/config/test_cc_ssh.py +@@ -101,11 +101,16 @@ class TestHandleSsh: + expected_calls = [mock.call(set(keys), user)] + expected_calls + assert expected_calls == m_setup_keys.call_args_list + ++ @pytest.mark.parametrize("fips_enabled", (True, False)) + @mock.patch(MODPATH + "glob.glob") + @mock.patch(MODPATH + "ug_util.normalize_users_groups") + @mock.patch(MODPATH + "os.path.exists") +- def test_handle_no_cfg(self, m_path_exists, m_nug, m_glob, m_setup_keys): ++ @mock.patch(MODPATH + "util.fips_enabled") ++ def test_handle_no_cfg( ++ self, m_fips, m_path_exists, m_nug, m_glob, m_setup_keys, fips_enabled ++ ): + """Test handle with no config ignores generating existing keyfiles.""" ++ m_fips.return_value = fips_enabled + cfg = {} + keys = ["key1"] + m_glob.return_value = [] # Return no matching keys to prevent removal +@@ -118,12 +123,22 @@ class TestHandleSsh: + options = ssh_util.DISABLE_USER_OPTS.replace("$USER", "NONE") + options = options.replace("$DISABLE_USER", "root") + m_glob.assert_called_once_with("/etc/ssh/ssh_host_*key*") +- assert [ +- mock.call("/etc/ssh/ssh_host_rsa_key"), +- mock.call("/etc/ssh/ssh_host_dsa_key"), +- mock.call("/etc/ssh/ssh_host_ecdsa_key"), +- mock.call("/etc/ssh/ssh_host_ed25519_key"), +- ] in m_path_exists.call_args_list ++ m_fips.assert_called_once() ++ ++ if not m_fips(): ++ expected_calls = [ ++ mock.call("/etc/ssh/ssh_host_rsa_key"), ++ mock.call("/etc/ssh/ssh_host_dsa_key"), ++ mock.call("/etc/ssh/ssh_host_ecdsa_key"), ++ mock.call("/etc/ssh/ssh_host_ed25519_key"), ++ ] ++ else: ++ # Enabled fips doesn't generate dsa or ed25519 ++ expected_calls = [ ++ mock.call("/etc/ssh/ssh_host_rsa_key"), ++ mock.call("/etc/ssh/ssh_host_ecdsa_key"), ++ ] ++ assert expected_calls in m_path_exists.call_args_list + assert [ + mock.call(set(keys), "root", options=options) + ] == m_setup_keys.call_args_list +@@ -131,8 +146,9 @@ class TestHandleSsh: + @mock.patch(MODPATH + "glob.glob") + @mock.patch(MODPATH + "ug_util.normalize_users_groups") + @mock.patch(MODPATH + "os.path.exists") ++ @mock.patch(MODPATH + "util.fips_enabled", return_value=False) + def test_dont_allow_public_ssh_keys( +- self, m_path_exists, m_nug, m_glob, m_setup_keys ++ self, m_fips, m_path_exists, m_nug, m_glob, m_setup_keys + ): + """Test allow_public_ssh_keys=False ignores ssh public keys from + platform. +@@ -176,8 +192,10 @@ class TestHandleSsh: + @mock.patch(MODPATH + "glob.glob") + @mock.patch(MODPATH + "ug_util.normalize_users_groups") + @mock.patch(MODPATH + "os.path.exists") ++ @mock.patch(MODPATH + "util.fips_enabled", return_value=False) + def test_handle_default_root( + self, ++ m_fips, + m_path_exists, + m_nug, + m_glob, +@@ -241,8 +259,10 @@ class TestHandleSsh: + @mock.patch(MODPATH + "glob.glob") + @mock.patch(MODPATH + "ug_util.normalize_users_groups") + @mock.patch(MODPATH + "os.path.exists") ++ @mock.patch(MODPATH + "util.fips_enabled", return_value=False) + def test_handle_publish_hostkeys( + self, ++ m_fips, + m_path_exists, + m_nug, + m_glob, +diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py +index 07142a86..17182d06 100644 +--- a/tests/unittests/test_util.py ++++ b/tests/unittests/test_util.py +@@ -1945,6 +1945,31 @@ class TestGetCmdline(helpers.TestCase): + self.assertEqual("abcd 123", ret) + + ++class TestFipsEnabled: ++ @pytest.mark.parametrize( ++ "fips_enabled_content,expected", ++ ( ++ pytest.param(None, False, id="false_when_no_fips_enabled_file"), ++ pytest.param("0\n", False, id="false_when_fips_disabled"), ++ pytest.param("1\n", True, id="true_when_fips_enabled"), ++ pytest.param("1", True, id="true_when_fips_enabled_no_newline"), ++ ), ++ ) ++ @mock.patch(M_PATH + "load_file") ++ def test_fips_enabled_based_on_proc_crypto( ++ self, load_file, fips_enabled_content, expected, tmpdir ++ ): ++ def fake_load_file(path): ++ assert path == "/proc/sys/crypto/fips_enabled" ++ if fips_enabled_content is None: ++ raise IOError("No file exists Bob") ++ return fips_enabled_content ++ ++ load_file.side_effect = fake_load_file ++ ++ assert expected is util.fips_enabled() ++ ++ + class TestLoadYaml(helpers.CiTestCase): + mydefault = "7b03a8ebace993d806255121073fed52" + with_logs = True diff --git a/SOURCES/0011-Revert-Manual-revert-Use-Network-Manager-and-Netplan.patch b/SOURCES/0011-Revert-Manual-revert-Use-Network-Manager-and-Netplan.patch new file mode 100644 index 0000000..bce0c00 --- /dev/null +++ b/SOURCES/0011-Revert-Manual-revert-Use-Network-Manager-and-Netplan.patch @@ -0,0 +1,93 @@ +From 0b0632f6c084a8ce95b53cb5125dc0f4107e6968 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Thu, 4 May 2023 15:34:43 +0530 +Subject: [PATCH] Revert "Manual revert "Use Network-Manager and Netplan as + default renderers for RHEL and Fedora (#1465)"" + +This reverts commit ecae81f98ce230266eb99671b74534a4ede660f0. + +This is patch 1 of the two patches that re-enables NM renderer. This change +can be ignored while rebasing to latest upstream. + +X-downstream-only: true +Signed-off-by: Ani Sinha +--- + cloudinit/net/renderers.py | 1 + + config/cloud.cfg.tmpl | 3 +++ + doc/rtd/reference/network-config.rst | 16 ++++++++++++++-- + 3 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/cloudinit/net/renderers.py b/cloudinit/net/renderers.py +index c92b9dcf..022ff938 100644 +--- a/cloudinit/net/renderers.py ++++ b/cloudinit/net/renderers.py +@@ -28,6 +28,7 @@ DEFAULT_PRIORITY = [ + "eni", + "sysconfig", + "netplan", ++ "network-manager", + "freebsd", + "netbsd", + "openbsd", +diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl +index 12f32c51..7238c102 100644 +--- a/config/cloud.cfg.tmpl ++++ b/config/cloud.cfg.tmpl +@@ -381,6 +381,9 @@ system_info: + {% elif variant in ["dragonfly"] %} + network: + renderers: ['freebsd'] ++{% elif variant in ["fedora"] or is_rhel %} ++ network: ++ renderers: ['netplan', 'network-manager', 'networkd', 'sysconfig', 'eni'] + {% elif variant == "openmandriva" %} + network: + renderers: ['network-manager', 'networkd'] +diff --git a/doc/rtd/reference/network-config.rst b/doc/rtd/reference/network-config.rst +index bc52afa5..ea331f1c 100644 +--- a/doc/rtd/reference/network-config.rst ++++ b/doc/rtd/reference/network-config.rst +@@ -176,6 +176,16 @@ this state, ``cloud-init`` delegates rendering of the configuration to + distro-supported formats. The following ``renderers`` are supported in + ``cloud-init``: + ++NetworkManager ++-------------- ++ ++`NetworkManager`_ is the standard Linux network configuration tool suite. It ++supports a wide range of networking setups. Configuration is typically stored ++in :file:`/etc/NetworkManager`. ++ ++It is the default for a number of Linux distributions; notably Fedora, ++CentOS/RHEL, and their derivatives. ++ + ENI + --- + +@@ -213,6 +223,7 @@ preference) is as follows: + - ENI + - Sysconfig + - Netplan ++- NetworkManager + - FreeBSD + - NetBSD + - OpenBSD +@@ -223,6 +234,7 @@ preference) is as follows: + + - **ENI**: using ``ifup``, ``ifdown`` to manage device setup/teardown + - **Netplan**: using ``netplan apply`` to manage device setup/teardown ++- **NetworkManager**: using ``nmcli`` to manage device setup/teardown + - **Networkd**: using ``ip`` to manage device setup/teardown + + When applying the policy, ``cloud-init`` checks if the current instance has the +@@ -232,8 +244,8 @@ supplying an updated configuration in cloud-config. :: + + system_info: + network: +- renderers: ['netplan', 'eni', 'sysconfig', 'freebsd', 'netbsd', 'openbsd'] +- activators: ['eni', 'netplan', 'networkd'] ++ renderers: ['netplan', 'network-manager', 'eni', 'sysconfig', 'freebsd', 'netbsd', 'openbsd'] ++ activators: ['eni', 'netplan', 'network-manager', 'networkd'] + + Network configuration tools + =========================== diff --git a/SOURCES/ci-Add-native-NetworkManager-support-1224.patch b/SOURCES/0012-Revert-Revert-Add-native-NetworkManager-support-1224.patch similarity index 58% rename from SOURCES/ci-Add-native-NetworkManager-support-1224.patch rename to SOURCES/0012-Revert-Revert-Add-native-NetworkManager-support-1224.patch index 8bcbcc7..2ae66c7 100644 --- a/SOURCES/ci-Add-native-NetworkManager-support-1224.patch +++ b/SOURCES/0012-Revert-Revert-Add-native-NetworkManager-support-1224.patch @@ -1,66 +1,32 @@ -From f0ae77cbf4a5e269da54fc2783a2a836023bbd86 Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Mon, 2 May 2022 14:42:52 +0200 -Subject: [PATCH 1/5] Add native NetworkManager support (#1224) +From 5822f72230a58d18dae8c3b76c02d4bf7a149e56 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Thu, 4 May 2023 15:39:17 +0530 +Subject: [PATCH] Revert "Revert "Add native NetworkManager support (#1224)"" -RH-Author: Emanuele Giuseppe Esposito -RH-MergeRequest: 24: Add native NetworkManager support (#1224) -RH-Commit: [1/3] 65231ba68460c505646807faf186c704d67678b5 (eesposit/cloud-init-centos-) -RH-Bugzilla: 2056964 -RH-Acked-by: Miroslav Rezanina -RH-Acked-by: Vitaly Kuznetsov +This reverts commit b1dd14ffafad2d2ca84326c525962b2ca086b292. -commit feda344e6cf9d37b09bc13cf333a717d1654c26c -Author: Lubomir Rintel -Date: Fri Feb 25 23:33:20 2022 +0100 +This is patch 2 of the two patches that re-enables NM renderer. This change can +be ignored while rebasing to latest upstream. - Add native NetworkManager support (#1224) - - Fedora currently relies on sysconfig/ifcfg renderer. This is not too great, - because Fedora (also RHEL since version 8) dropped support for the legacy - network service that uses ifcfg files long ago. - - In turn, Fedora ended up patching cloud-init downstream to utilize - NetworkManager's ifcfg compatibility mode [1]. This seems to have worked - for a while, nevertheless the NetworkManager's ifcfg backend is reaching - the end of its useful life too [2]. - - [1] https://src.fedoraproject.org/rpms/cloud-init/blob/rawhide/f/cloud-init-21.3-nm-controlled.patch - [2] https://fedoraproject.org/wiki/Changes/NoIfcfgFiles - - Let's not mangle things downstream and make vanilla cloud-init work great - on Fedora instead. - - This also means that the sysconfig compatibility with - Network Manager was removed. - - Firstly, this relies upon the fact that you can get ifcfg support by adding - it to NetworkManager.conf. That is not guaranteed and certainly will not - be case in future. - - Secondly, cloud-init always generates configuration with - NM_CONTROLLED=no, so the generated ifcfg files are no good for - NetworkManager. Fedora patches around this by just removing those lines - in their cloud-init package. - -Signed-off-by: Emanuele Giuseppe Esposito +X-downstream-only: true +Signed-off-by: Ani Sinha --- - cloudinit/cmd/devel/net_convert.py | 14 +- - cloudinit/net/activators.py | 25 +- - cloudinit/net/network_manager.py | 377 +++++++ - cloudinit/net/renderers.py | 3 + - cloudinit/net/sysconfig.py | 37 +- - tests/unittests/test_net.py | 1270 +++++++++++++++++++++--- - tests/unittests/test_net_activators.py | 93 +- - 7 files changed, 1625 insertions(+), 194 deletions(-) + cloudinit/cmd/devel/net_convert.py | 14 +- + cloudinit/net/activators.py | 25 +- + cloudinit/net/network_manager.py | 393 ++++++++++++++++ + cloudinit/net/renderers.py | 2 + + cloudinit/net/sysconfig.py | 42 +- + tests/unittests/test_net.py | 597 ++++++++++++++++++++----- + tests/unittests/test_net_activators.py | 11 +- + 7 files changed, 923 insertions(+), 161 deletions(-) create mode 100644 cloudinit/net/network_manager.py diff --git a/cloudinit/cmd/devel/net_convert.py b/cloudinit/cmd/devel/net_convert.py -index 18b1e7ff..647fe07b 100755 +index 1a0a31ac..eee49860 100755 --- a/cloudinit/cmd/devel/net_convert.py +++ b/cloudinit/cmd/devel/net_convert.py -@@ -7,7 +7,14 @@ import os - import sys +@@ -10,7 +10,14 @@ import sys + import yaml from cloudinit import distros, log, safeyaml -from cloudinit.net import eni, netplan, network_state, networkd, sysconfig @@ -73,9 +39,9 @@ index 18b1e7ff..647fe07b 100755 + sysconfig, +) from cloudinit.sources import DataSourceAzure as azure - from cloudinit.sources import DataSourceOVF as ovf from cloudinit.sources.helpers import openstack -@@ -74,7 +81,7 @@ def get_parser(parser=None): + from cloudinit.sources.helpers.vmware.imc import guestcust_util +@@ -77,7 +84,7 @@ def get_parser(parser=None): parser.add_argument( "-O", "--output-kind", @@ -84,7 +50,7 @@ index 18b1e7ff..647fe07b 100755 required=True, help="The network config format to emit", ) -@@ -148,6 +155,9 @@ def handle_args(name, args): +@@ -150,6 +157,9 @@ def handle_args(name, args): elif args.output_kind == "sysconfig": r_cls = sysconfig.Renderer config = distro.renderer_configs.get("sysconfig") @@ -95,7 +61,7 @@ index 18b1e7ff..647fe07b 100755 raise RuntimeError("Invalid output_kind") diff --git a/cloudinit/net/activators.py b/cloudinit/net/activators.py -index e80c26df..edbc0c06 100644 +index d9a8c4d7..7d11a02c 100644 --- a/cloudinit/net/activators.py +++ b/cloudinit/net/activators.py @@ -1,15 +1,14 @@ @@ -103,7 +69,7 @@ index e80c26df..edbc0c06 100644 import logging -import os from abc import ABC, abstractmethod - from typing import Iterable, List, Type + from typing import Dict, Iterable, List, Optional, Type, Union from cloudinit import subp, util from cloudinit.net.eni import available as eni_available @@ -159,10 +125,10 @@ index e80c26df..edbc0c06 100644 diff --git a/cloudinit/net/network_manager.py b/cloudinit/net/network_manager.py new file mode 100644 -index 00000000..79b0fe0b +index 00000000..53763d15 --- /dev/null +++ b/cloudinit/net/network_manager.py -@@ -0,0 +1,377 @@ +@@ -0,0 +1,393 @@ +# Copyright 2022 Red Hat, Inc. +# +# Author: Lubomir Rintel @@ -176,15 +142,16 @@ index 00000000..79b0fe0b +import itertools +import os +import uuid ++from typing import Optional + +from cloudinit import log as logging +from cloudinit import subp, util -+ -+from . import renderer -+from .network_state import is_ipv6_addr, subnet_is_ipv6 ++from cloudinit.net import is_ipv6_address, renderer, subnet_is_ipv6 ++from cloudinit.net.network_state import NetworkState + +NM_RUN_DIR = "/etc/NetworkManager" +NM_LIB_DIR = "/usr/lib/NetworkManager" ++NM_CFG_FILE = "/etc/NetworkManager/NetworkManager.conf" +LOG = logging.getLogger(__name__) + + @@ -233,7 +200,7 @@ index 00000000..79b0fe0b + + method_map = { + "static": "manual", -+ "dhcp6": "dhcp", ++ "dhcp6": "auto", + "ipv6_slaac": "auto", + "ipv6_dhcpv6-stateless": "auto", + "ipv6_dhcpv6-stateful": "auto", @@ -260,8 +227,6 @@ index 00000000..79b0fe0b + + self.config[family]["method"] = method + self._set_default(family, "may-fail", "false") -+ if family == "ipv6": -+ self._set_default(family, "addr-gen-mode", "stable-privacy") + + def _add_numbered(self, section, key_prefix, value): + """ @@ -302,7 +267,7 @@ index 00000000..79b0fe0b + # together. We might be getting an IPv6 name server while + # we're dealing with an IPv4 subnet. Sort this out by figuring + # out the correct family and making sure a valid section exist. -+ family = "ipv6" if is_ipv6_addr(dns) else "ipv4" ++ family = "ipv6" if is_ipv6_address(dns) else "ipv4" + self._set_default(family, "method", "disabled") + + self._set_default(family, "dns", "") @@ -508,7 +473,12 @@ index 00000000..79b0fe0b + # Well, what can we do... + return con_id + -+ def render_network_state(self, network_state, templates=None, target=None): ++ def render_network_state( ++ self, ++ network_state: NetworkState, ++ templates: Optional[dict] = None, ++ target=None, ++ ) -> None: + # First pass makes sure there's NMConnections for all known + # interfaces that have UUIDs that can be linked to from related + # interfaces @@ -535,16 +505,28 @@ index 00000000..79b0fe0b + + +def available(target=None): -+ target_nm_dir = subp.target_path(target, NM_LIB_DIR) -+ return os.path.exists(target_nm_dir) ++ # TODO: Move `uses_systemd` to a more appropriate location ++ # It is imported here to avoid circular import ++ from cloudinit.distros import uses_systemd ++ ++ config_present = os.path.isfile(subp.target_path(target, path=NM_CFG_FILE)) ++ nmcli_present = subp.which("nmcli", target=target) ++ service_active = True ++ if uses_systemd(): ++ try: ++ subp.subp(["systemctl", "is-enabled", "NetworkManager.service"]) ++ except subp.ProcessExecutionError: ++ service_active = False ++ ++ return config_present and bool(nmcli_present) and service_active + + +# vi: ts=4 expandtab diff --git a/cloudinit/net/renderers.py b/cloudinit/net/renderers.py -index c755f04c..7edc34b5 100644 +index 022ff938..fcf7feba 100644 --- a/cloudinit/net/renderers.py +++ b/cloudinit/net/renderers.py -@@ -8,6 +8,7 @@ from . import ( +@@ -8,6 +8,7 @@ from cloudinit.net import ( freebsd, netbsd, netplan, @@ -560,31 +542,33 @@ index c755f04c..7edc34b5 100644 "networkd": networkd, "openbsd": openbsd, "sysconfig": sysconfig, -@@ -28,6 +30,7 @@ DEFAULT_PRIORITY = [ - "eni", - "sysconfig", - "netplan", -+ "network-manager", - "freebsd", - "netbsd", - "openbsd", diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py -index b50035b5..2a45a4fa 100644 +index e08c0c69..b8786fb7 100644 --- a/cloudinit/net/sysconfig.py +++ b/cloudinit/net/sysconfig.py -@@ -5,8 +5,6 @@ import io - import os +@@ -6,8 +6,6 @@ import os import re + from typing import Mapping, Optional -from configobj import ConfigObj - from cloudinit import log as logging from cloudinit import subp, util from cloudinit.distros.parsers import networkmanager_conf, resolv_conf -@@ -66,24 +64,6 @@ def _quote_value(value): +@@ -37,7 +35,7 @@ KNOWN_DISTROS = [ + "TencentOS", + "virtuozzo", + ] +-NM_CFG_FILE = "/etc/NetworkManager/NetworkManager.conf" ++ + + def _make_header(sep="#"): + lines = [ +@@ -68,26 +66,7 @@ def _quote_value(value): return value +- -def enable_ifcfg_rh(path): - """Add ifcfg-rh to NetworkManager.cfg plugins if main section is present""" - config = ConfigObj(path) @@ -603,19 +587,21 @@ index b50035b5..2a45a4fa 100644 - LOG.debug("Enabled ifcfg-rh NetworkManager plugins") - - - class ConfigMap(object): +-class ConfigMap(object): ++class ConfigMap: """Sysconfig like dictionary object.""" -@@ -1032,8 +1012,6 @@ class Renderer(renderer.Renderer): - netrules_content = self._render_persistent_net(network_state) - netrules_path = subp.target_path(target, self.netrules_path) - util.write_file(netrules_path, netrules_content, file_mode) + # Why does redhat prefer yes/no to true/false?? +@@ -1040,8 +1019,6 @@ class Renderer(renderer.Renderer): + mode=file_mode, + preserve_mode=True, + ) - if available_nm(target=target): - enable_ifcfg_rh(subp.target_path(target, path=NM_CFG_FILE)) sysconfig_path = subp.target_path(target, templates.get("control")) # Distros configuring /etc/sysconfig/network as a file e.g. Centos -@@ -1072,14 +1050,9 @@ def _supported_vlan_names(rdev, vid): +@@ -1080,14 +1057,9 @@ def _supported_vlan_names(rdev, vid): def available(target=None): @@ -632,7 +618,7 @@ index b50035b5..2a45a4fa 100644 expected = ["ifup", "ifdown"] search = ["/sbin", "/usr/sbin"] for p in expected: -@@ -1096,10 +1069,4 @@ def available_sysconfig(target=None): +@@ -1104,10 +1076,4 @@ def available_sysconfig(target=None): return False @@ -644,18 +630,18 @@ index b50035b5..2a45a4fa 100644 - # vi: ts=4 expandtab diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py -index 591241b3..ef21ad76 100644 +index 4434b350..0f523ff8 100644 --- a/tests/unittests/test_net.py +++ b/tests/unittests/test_net.py -@@ -21,6 +21,7 @@ from cloudinit.net import ( - interface_has_own_mac, +@@ -23,6 +23,7 @@ from cloudinit.net import ( + mask_and_ipv4_to_bcast_addr, natural_sort_key, netplan, + network_manager, network_state, networkd, renderers, -@@ -611,6 +612,37 @@ dns = none +@@ -616,6 +617,37 @@ dns = none ), ), ], @@ -693,7 +679,7 @@ index 591241b3..ef21ad76 100644 }, { "in_data": { -@@ -1073,6 +1105,50 @@ NETWORK_CONFIGS = { +@@ -1078,6 +1110,50 @@ NETWORK_CONFIGS = { USERCTL=no""" ), }, @@ -744,208 +730,7 @@ index 591241b3..ef21ad76 100644 "yaml": textwrap.dedent( """ version: 1 -@@ -1145,6 +1221,34 @@ NETWORK_CONFIGS = { - STARTMODE=auto""" - ) - }, -+ "expected_network_manager": { -+ "cloud-init-iface0.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init iface0 -+ uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 -+ type=ethernet -+ interface-name=iface0 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ -+ [ipv4] -+ method=auto -+ may-fail=false -+ -+ [ipv6] -+ method=dhcp -+ may-fail=false -+ addr-gen-mode=stable-privacy -+ -+ """ -+ ), -+ }, - "yaml": textwrap.dedent( - """\ - version: 1 -@@ -1247,6 +1351,37 @@ NETWORK_CONFIGS = { - """ - ), - }, -+ "expected_network_manager": { -+ "cloud-init-iface0.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init iface0 -+ uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 -+ type=ethernet -+ interface-name=iface0 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ mtu=9000 -+ -+ [ipv4] -+ method=manual -+ may-fail=false -+ address1=192.168.14.2/24 -+ -+ [ipv6] -+ method=manual -+ may-fail=false -+ addr-gen-mode=stable-privacy -+ address1=2001:1::1/64 -+ -+ """ -+ ), -+ }, - }, - "v6_and_v4": { - "expected_sysconfig_opensuse": { -@@ -1257,6 +1392,34 @@ NETWORK_CONFIGS = { - STARTMODE=auto""" - ) - }, -+ "expected_network_manager": { -+ "cloud-init-iface0.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init iface0 -+ uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 -+ type=ethernet -+ interface-name=iface0 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ -+ [ipv6] -+ method=dhcp -+ may-fail=false -+ addr-gen-mode=stable-privacy -+ -+ [ipv4] -+ method=auto -+ may-fail=false -+ -+ """ -+ ), -+ }, - "yaml": textwrap.dedent( - """\ - version: 1 -@@ -1330,6 +1493,30 @@ NETWORK_CONFIGS = { - """ - ), - }, -+ "expected_network_manager": { -+ "cloud-init-iface0.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init iface0 -+ uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 -+ type=ethernet -+ interface-name=iface0 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ -+ [ipv6] -+ method=dhcp -+ may-fail=false -+ addr-gen-mode=stable-privacy -+ -+ """ -+ ), -+ }, - }, - "dhcpv6_accept_ra": { - "expected_eni": textwrap.dedent( -@@ -1537,6 +1724,30 @@ NETWORK_CONFIGS = { - """ - ), - }, -+ "expected_network_manager": { -+ "cloud-init-iface0.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init iface0 -+ uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 -+ type=ethernet -+ interface-name=iface0 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ -+ [ipv6] -+ method=auto -+ may-fail=false -+ addr-gen-mode=stable-privacy -+ -+ """ -+ ), -+ }, - }, - "static6": { - "yaml": textwrap.dedent( -@@ -1625,6 +1836,30 @@ NETWORK_CONFIGS = { - """ - ), - }, -+ "expected_network_manager": { -+ "cloud-init-iface0.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init iface0 -+ uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 -+ type=ethernet -+ interface-name=iface0 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ -+ [ipv6] -+ method=auto -+ may-fail=false -+ addr-gen-mode=stable-privacy -+ -+ """ -+ ), -+ }, - }, - "dhcpv6_stateful": { - "expected_eni": textwrap.dedent( -@@ -1724,6 +1959,29 @@ NETWORK_CONFIGS = { +@@ -1883,6 +1959,29 @@ NETWORK_CONFIGS = { """ ), }, @@ -975,7 +760,7 @@ index 591241b3..ef21ad76 100644 "yaml_v2": textwrap.dedent( """\ version: 2 -@@ -1777,6 +2035,30 @@ NETWORK_CONFIGS = { +@@ -1936,6 +2035,30 @@ NETWORK_CONFIGS = { """ ), }, @@ -1006,304 +791,7 @@ index 591241b3..ef21ad76 100644 "yaml_v2": textwrap.dedent( """\ version: 2 -@@ -2215,6 +2497,254 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true - USERCTL=no""" - ), - }, -+ "expected_network_manager": { -+ "cloud-init-eth3.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init eth3 -+ uuid=b7e95dda-7746-5bf8-bf33-6e5f3c926790 -+ type=ethernet -+ slave-type=bridge -+ master=dee46ce4-af7a-5e7c-aa08-b25533ae9213 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ mac-address=66:BB:9F:2C:E8:80 -+ -+ """ -+ ), -+ "cloud-init-eth5.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init eth5 -+ uuid=5fda13c7-9942-5e90-a41b-1d043bd725dc -+ type=ethernet -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ mac-address=98:BB:9F:2C:E8:8A -+ -+ [ipv4] -+ method=auto -+ may-fail=false -+ -+ """ -+ ), -+ "cloud-init-ib0.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init ib0 -+ uuid=11a1dda7-78b4-5529-beba-d9b5f549ad7b -+ type=infiniband -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [infiniband] -+ transport-mode=datagram -+ mtu=9000 -+ mac-address=A0:00:02:20:FE:80:00:00:00:00:00:00:EC:0D:9A:03:00:15:E2:C1 -+ -+ [ipv4] -+ method=manual -+ may-fail=false -+ address1=192.168.200.7/24 -+ -+ """ -+ ), -+ "cloud-init-bond0.200.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init bond0.200 -+ uuid=88984a9c-ff22-5233-9267-86315e0acaa7 -+ type=vlan -+ interface-name=bond0.200 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [vlan] -+ id=200 -+ parent=54317911-f840-516b-a10d-82cb4c1f075c -+ -+ [ipv4] -+ method=auto -+ may-fail=false -+ -+ """ -+ ), -+ "cloud-init-eth0.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init eth0 -+ uuid=1dd9a779-d327-56e1-8454-c65e2556c12c -+ type=ethernet -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ mac-address=C0:D6:9F:2C:E8:80 -+ -+ """ -+ ), -+ "cloud-init-eth4.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init eth4 -+ uuid=e27e4959-fb50-5580-b9a4-2073554627b9 -+ type=ethernet -+ slave-type=bridge -+ master=dee46ce4-af7a-5e7c-aa08-b25533ae9213 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ mac-address=98:BB:9F:2C:E8:80 -+ -+ """ -+ ), -+ "cloud-init-eth1.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init eth1 -+ uuid=3c50eb47-7260-5a6d-801d-bd4f587d6b58 -+ type=ethernet -+ slave-type=bond -+ master=54317911-f840-516b-a10d-82cb4c1f075c -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ mac-address=AA:D6:9F:2C:E8:80 -+ -+ """ -+ ), -+ "cloud-init-br0.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init br0 -+ uuid=dee46ce4-af7a-5e7c-aa08-b25533ae9213 -+ type=bridge -+ interface-name=br0 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [bridge] -+ stp=false -+ priority=22 -+ mac-address=BB:BB:BB:BB:BB:AA -+ -+ [ipv4] -+ method=manual -+ may-fail=false -+ address1=192.168.14.2/24 -+ -+ [ipv6] -+ method=manual -+ may-fail=false -+ addr-gen-mode=stable-privacy -+ address1=2001:1::1/64 -+ route1=::/0,2001:4800:78ff:1b::1 -+ -+ """ -+ ), -+ "cloud-init-eth0.101.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init eth0.101 -+ uuid=b5acec5e-db80-5935-8b02-0d5619fc42bf -+ type=vlan -+ interface-name=eth0.101 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [vlan] -+ id=101 -+ parent=1dd9a779-d327-56e1-8454-c65e2556c12c -+ -+ [ipv4] -+ method=manual -+ may-fail=false -+ address1=192.168.0.2/24 -+ gateway=192.168.0.1 -+ dns=192.168.0.10;10.23.23.134; -+ dns-search=barley.maas;sacchromyces.maas;brettanomyces.maas; -+ address2=192.168.2.10/24 -+ -+ """ -+ ), -+ "cloud-init-bond0.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init bond0 -+ uuid=54317911-f840-516b-a10d-82cb4c1f075c -+ type=bond -+ interface-name=bond0 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [bond] -+ mode=active-backup -+ miimon=100 -+ xmit_hash_policy=layer3+4 -+ -+ [ipv6] -+ method=dhcp -+ may-fail=false -+ addr-gen-mode=stable-privacy -+ -+ """ -+ ), -+ "cloud-init-eth2.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init eth2 -+ uuid=5559a242-3421-5fdd-896e-9cb8313d5804 -+ type=ethernet -+ slave-type=bond -+ master=54317911-f840-516b-a10d-82cb4c1f075c -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ mac-address=C0:BB:9F:2C:E8:80 -+ -+ """ -+ ), -+ }, - "yaml": textwrap.dedent( - """ - version: 1 -@@ -2403,10 +2933,10 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true - - type: static - address: 2001:1::1/92 - routes: -- - gateway: 2001:67c:1562:1 -+ - gateway: 2001:67c:1562::1 - network: 2001:67c:1 - netmask: "ffff:ffff::" -- - gateway: 3001:67c:1562:1 -+ - gateway: 3001:67c:15::1 - network: 3001:67c:1 - netmask: "ffff:ffff::" - metric: 10000 -@@ -2451,10 +2981,10 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true - - to: 10.1.3.0/24 - via: 192.168.0.3 - - to: 2001:67c:1/32 -- via: 2001:67c:1562:1 -+ via: 2001:67c:1562::1 - - metric: 10000 - to: 3001:67c:1/32 -- via: 3001:67c:1562:1 -+ via: 3001:67c:15::1 - """ - ), - "expected_eni": textwrap.dedent( -@@ -2514,11 +3044,11 @@ iface bond0 inet static - # control-alias bond0 - iface bond0 inet6 static - address 2001:1::1/92 -- post-up route add -A inet6 2001:67c:1/32 gw 2001:67c:1562:1 || true -- pre-down route del -A inet6 2001:67c:1/32 gw 2001:67c:1562:1 || true -- post-up route add -A inet6 3001:67c:1/32 gw 3001:67c:1562:1 metric 10000 \ -+ post-up route add -A inet6 2001:67c:1/32 gw 2001:67c:1562::1 || true -+ pre-down route del -A inet6 2001:67c:1/32 gw 2001:67c:1562::1 || true -+ post-up route add -A inet6 3001:67c:1/32 gw 3001:67c:15::1 metric 10000 \ - || true -- pre-down route del -A inet6 3001:67c:1/32 gw 3001:67c:1562:1 metric 10000 \ -+ pre-down route del -A inet6 3001:67c:1/32 gw 3001:67c:15::1 metric 10000 \ - || true - """ - ), -@@ -2561,8 +3091,8 @@ iface bond0 inet6 static +@@ -2969,8 +3092,8 @@ iface bond0 inet6 static - to: 2001:67c:1562:8007::1/64 via: 2001:67c:1562:8007::aac:40b2 - metric: 10000 @@ -1314,7 +802,7 @@ index 591241b3..ef21ad76 100644 """ ), "expected_netplan-v2": textwrap.dedent( -@@ -2594,8 +3124,8 @@ iface bond0 inet6 static +@@ -3002,8 +3125,8 @@ iface bond0 inet6 static - to: 2001:67c:1562:8007::1/64 via: 2001:67c:1562:8007::aac:40b2 - metric: 10000 @@ -1325,194 +813,11 @@ index 591241b3..ef21ad76 100644 ethernets: eth0: match: -@@ -2694,8 +3224,8 @@ iface bond0 inet6 static - """\ - # Created by cloud-init on instance boot automatically, do not edit. - # -- 2001:67c:1/32 via 2001:67c:1562:1 dev bond0 -- 3001:67c:1/32 via 3001:67c:1562:1 metric 10000 dev bond0 -+ 2001:67c:1/32 via 2001:67c:1562::1 dev bond0 -+ 3001:67c:1/32 via 3001:67c:15::1 metric 10000 dev bond0 - """ - ), - "route-bond0": textwrap.dedent( -@@ -2718,6 +3248,88 @@ iface bond0 inet6 static - """ - ), - }, -+ "expected_network_manager": { -+ "cloud-init-bond0s0.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init bond0s0 -+ uuid=09d0b5b9-67e7-5577-a1af-74d1cf17a71e -+ type=ethernet -+ slave-type=bond -+ master=54317911-f840-516b-a10d-82cb4c1f075c -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ mac-address=AA:BB:CC:DD:E8:00 -+ -+ """ -+ ), -+ "cloud-init-bond0s1.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init bond0s1 -+ uuid=4d9aca96-b515-5630-ad83-d13daac7f9d0 -+ type=ethernet -+ slave-type=bond -+ master=54317911-f840-516b-a10d-82cb4c1f075c -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ mac-address=AA:BB:CC:DD:E8:01 -+ -+ """ -+ ), -+ "cloud-init-bond0.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init bond0 -+ uuid=54317911-f840-516b-a10d-82cb4c1f075c -+ type=bond -+ interface-name=bond0 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [bond] -+ mode=active-backup -+ miimon=100 -+ xmit_hash_policy=layer3+4 -+ num_grat_arp=5 -+ downdelay=10 -+ updelay=20 -+ fail_over_mac=active -+ primary_reselect=always -+ primary=bond0s0 -+ -+ [ipv4] -+ method=manual -+ may-fail=false -+ address1=192.168.0.2/24 -+ gateway=192.168.0.1 -+ route1=10.1.3.0/24,192.168.0.3 -+ address2=192.168.1.2/24 -+ -+ [ipv6] -+ method=manual -+ may-fail=false -+ addr-gen-mode=stable-privacy -+ address1=2001:1::1/92 -+ route1=2001:67c:1/32,2001:67c:1562::1 -+ route2=3001:67c:1/32,3001:67c:15::1 -+ -+ """ -+ ), -+ }, - }, - "vlan": { - "yaml": textwrap.dedent( -@@ -2801,6 +3413,58 @@ iface bond0 inet6 static - VLAN=yes""" - ), - }, -+ "expected_network_manager": { -+ "cloud-init-en0.99.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init en0.99 -+ uuid=f594e2ed-f107-51df-b225-1dc530a5356b -+ type=vlan -+ interface-name=en0.99 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [vlan] -+ id=99 -+ parent=e0ca478b-8d84-52ab-8fae-628482c629b5 -+ -+ [ipv4] -+ method=manual -+ may-fail=false -+ address1=192.168.2.2/24 -+ address2=192.168.1.2/24 -+ gateway=192.168.1.1 -+ -+ [ipv6] -+ method=manual -+ may-fail=false -+ addr-gen-mode=stable-privacy -+ address1=2001:1::bbbb/96 -+ route1=::/0,2001:1::1 -+ -+ """ -+ ), -+ "cloud-init-en0.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init en0 -+ uuid=e0ca478b-8d84-52ab-8fae-628482c629b5 -+ type=ethernet -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ mac-address=AA:BB:CC:DD:E8:00 -+ -+ """ -+ ), -+ }, - }, - "bridge": { - "yaml": textwrap.dedent( -@@ -2909,6 +3573,82 @@ iface bond0 inet6 static +@@ -3651,6 +3774,73 @@ iface bond0 inet6 static """ ), }, + "expected_network_manager": { -+ "cloud-init-br0.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init br0 -+ uuid=dee46ce4-af7a-5e7c-aa08-b25533ae9213 -+ type=bridge -+ interface-name=br0 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [bridge] -+ stp=false -+ priority=22 -+ -+ [ipv4] -+ method=manual -+ may-fail=false -+ address1=192.168.2.2/24 -+ -+ """ -+ ), + "cloud-init-eth0.nmconnection": textwrap.dedent( + """\ + # Generated by cloud-init. Changes will be lost. @@ -1521,8 +826,6 @@ index 591241b3..ef21ad76 100644 + id=cloud-init eth0 + uuid=1dd9a779-d327-56e1-8454-c65e2556c12c + type=ethernet -+ slave-type=bridge -+ master=dee46ce4-af7a-5e7c-aa08-b25533ae9213 + + [user] + org.freedesktop.NetworkManager.origin=cloud-init @@ -1530,81 +833,6 @@ index 591241b3..ef21ad76 100644 + [ethernet] + mac-address=52:54:00:12:34:00 + -+ [ipv6] -+ method=manual -+ may-fail=false -+ addr-gen-mode=stable-privacy -+ address1=2001:1::100/96 -+ -+ """ -+ ), -+ "cloud-init-eth1.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. -+ -+ [connection] -+ id=cloud-init eth1 -+ uuid=3c50eb47-7260-5a6d-801d-bd4f587d6b58 -+ type=ethernet -+ slave-type=bridge -+ master=dee46ce4-af7a-5e7c-aa08-b25533ae9213 -+ -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init -+ -+ [ethernet] -+ mac-address=52:54:00:12:34:01 -+ -+ [ipv6] -+ method=manual -+ may-fail=false -+ addr-gen-mode=stable-privacy -+ address1=2001:1::101/96 -+ -+ """ -+ ), -+ }, - }, - "manual": { - "yaml": textwrap.dedent( -@@ -3037,28 +3777,95 @@ iface bond0 inet6 static - """ - ), - }, -- }, --} -+ "expected_network_manager": { -+ "cloud-init-eth0.nmconnection": textwrap.dedent( -+ """\ -+ # Generated by cloud-init. Changes will be lost. - -+ [connection] -+ id=cloud-init eth0 -+ uuid=1dd9a779-d327-56e1-8454-c65e2556c12c -+ type=ethernet - --CONFIG_V1_EXPLICIT_LOOPBACK = { -- "version": 1, -- "config": [ -- { -- "name": "eth0", -- "type": "physical", -- "subnets": [{"control": "auto", "type": "dhcp"}], -- }, -- { -- "name": "lo", -- "type": "loopback", -- "subnets": [{"control": "auto", "type": "loopback"}], -- }, -- ], --} -+ [user] -+ org.freedesktop.NetworkManager.origin=cloud-init - -+ [ethernet] -+ mac-address=52:54:00:12:34:00 - --CONFIG_V1_SIMPLE_SUBNET = { + [ipv4] + method=manual + may-fail=false @@ -1656,32 +884,10 @@ index 591241b3..ef21ad76 100644 + """ + ), + }, -+ }, -+} -+ -+ -+CONFIG_V1_EXPLICIT_LOOPBACK = { -+ "version": 1, -+ "config": [ -+ { -+ "name": "eth0", -+ "type": "physical", -+ "subnets": [{"control": "auto", "type": "dhcp"}], -+ }, -+ { -+ "name": "lo", -+ "type": "loopback", -+ "subnets": [{"control": "auto", "type": "loopback"}], -+ }, -+ ], -+} -+ -+ -+CONFIG_V1_SIMPLE_SUBNET = { - "version": 1, - "config": [ - { -@@ -3497,7 +4304,6 @@ class TestRhelSysConfigRendering(CiTestCase): + }, + "v2-dev-name-via-mac-lookup": { + "expected_sysconfig_rhel": { +@@ -4149,7 +4339,6 @@ class TestRhelSysConfigRendering(CiTestCase): with_logs = True @@ -1689,7 +895,7 @@ index 591241b3..ef21ad76 100644 scripts_dir = "/etc/sysconfig/network-scripts" header = ( "# Created by cloud-init on instance boot automatically, " -@@ -4072,78 +4878,6 @@ USERCTL=no +@@ -4724,78 +4913,6 @@ USERCTL=no self._compare_files_to_expected(entry[self.expected_name], found) self._assert_headers(found) @@ -1768,7 +974,7 @@ index 591241b3..ef21ad76 100644 def test_netplan_dhcp_false_disable_dhcp_in_state(self): """netplan config with dhcp[46]: False should not add dhcp in state""" net_config = yaml.load(NETPLAN_DHCP_FALSE) -@@ -4699,6 +5433,281 @@ STARTMODE=auto +@@ -5492,6 +5609,281 @@ STARTMODE=auto self._assert_headers(found) @@ -2050,7 +1256,7 @@ index 591241b3..ef21ad76 100644 class TestEniNetRendering(CiTestCase): @mock.patch("cloudinit.net.util.get_cmdline", return_value="root=myroot") @mock.patch("cloudinit.net.sys_dev_path") -@@ -6136,9 +7145,9 @@ class TestNetworkdRoundTrip(CiTestCase): +@@ -7259,9 +7651,9 @@ class TestNetworkdRoundTrip(CiTestCase): class TestRenderersSelect: @pytest.mark.parametrize( @@ -2062,7 +1268,7 @@ index 591241b3..ef21ad76 100644 ( net.RendererNotFoundError, False, -@@ -6146,52 +7155,51 @@ class TestRenderersSelect: +@@ -7269,52 +7661,51 @@ class TestRenderersSelect: False, False, False, @@ -2137,7 +1343,7 @@ index 591241b3..ef21ad76 100644 m_networkd_avail.return_value = networkd # networkd presence if isinstance(renderer_selected, str): (renderer_name, _rnd_class) = renderers.select( -@@ -6249,7 +7257,7 @@ class TestNetRenderers(CiTestCase): +@@ -7372,7 +7763,7 @@ class TestNetRenderers(CiTestCase): priority=["sysconfig", "eni"], ) @@ -2147,35 +1353,10 @@ index 591241b3..ef21ad76 100644 def test_sysconfig_available_uses_variant_mapping(self, m_info, m_avail): m_avail.return_value = True diff --git a/tests/unittests/test_net_activators.py b/tests/unittests/test_net_activators.py -index 3c29e2f7..4525c49c 100644 +index b735ea9e..afd9056a 100644 --- a/tests/unittests/test_net_activators.py +++ b/tests/unittests/test_net_activators.py -@@ -41,18 +41,20 @@ NETPLAN_CALL_LIST = [ - - @pytest.fixture - def available_mocks(): -- mocks = namedtuple("Mocks", "m_which, m_file") -+ mocks = namedtuple("Mocks", "m_which, m_file, m_exists") - with patch("cloudinit.subp.which", return_value=True) as m_which: - with patch("os.path.isfile", return_value=True) as m_file: -- yield mocks(m_which, m_file) -+ with patch("os.path.exists", return_value=True) as m_exists: -+ yield mocks(m_which, m_file, m_exists) - - - @pytest.fixture - def unavailable_mocks(): -- mocks = namedtuple("Mocks", "m_which, m_file") -+ mocks = namedtuple("Mocks", "m_which, m_file, m_exists") - with patch("cloudinit.subp.which", return_value=False) as m_which: - with patch("os.path.isfile", return_value=False) as m_file: -- yield mocks(m_which, m_file) -+ with patch("os.path.exists", return_value=False) as m_exists: -+ yield mocks(m_which, m_file, m_exists) - - - class TestSearchAndSelect: -@@ -113,10 +115,6 @@ NETPLAN_AVAILABLE_CALLS = [ +@@ -139,10 +139,6 @@ NETPLAN_AVAILABLE_CALLS = [ (("netplan",), {"search": ["/usr/sbin", "/sbin"], "target": None}), ] @@ -2186,7 +1367,7 @@ index 3c29e2f7..4525c49c 100644 NETWORKD_AVAILABLE_CALLS = [ (("ip",), {"search": ["/usr/sbin", "/bin"], "target": None}), (("systemctl",), {"search": ["/usr/sbin", "/bin"], "target": None}), -@@ -128,7 +126,6 @@ NETWORKD_AVAILABLE_CALLS = [ +@@ -154,7 +150,6 @@ NETWORKD_AVAILABLE_CALLS = [ [ (IfUpDownActivator, IF_UP_DOWN_AVAILABLE_CALLS), (NetplanActivator, NETPLAN_AVAILABLE_CALLS), @@ -2194,82 +1375,7 @@ index 3c29e2f7..4525c49c 100644 (NetworkdActivator, NETWORKD_AVAILABLE_CALLS), ], ) -@@ -144,8 +141,72 @@ IF_UP_DOWN_BRING_UP_CALL_LIST = [ - ] - - NETWORK_MANAGER_BRING_UP_CALL_LIST = [ -- ((["nmcli", "connection", "up", "ifname", "eth0"],), {}), -- ((["nmcli", "connection", "up", "ifname", "eth1"],), {}), -+ ( -+ ( -+ [ -+ "nmcli", -+ "connection", -+ "load", -+ "".join( -+ [ -+ "/etc/NetworkManager/system-connections", -+ "/cloud-init-eth0.nmconnection", -+ ] -+ ), -+ ], -+ ), -+ {}, -+ ), -+ ( -+ ( -+ [ -+ "nmcli", -+ "connection", -+ "up", -+ "filename", -+ "".join( -+ [ -+ "/etc/NetworkManager/system-connections", -+ "/cloud-init-eth0.nmconnection", -+ ] -+ ), -+ ], -+ ), -+ {}, -+ ), -+ ( -+ ( -+ [ -+ "nmcli", -+ "connection", -+ "load", -+ "".join( -+ [ -+ "/etc/NetworkManager/system-connections", -+ "/cloud-init-eth1.nmconnection", -+ ] -+ ), -+ ], -+ ), -+ {}, -+ ), -+ ( -+ ( -+ [ -+ "nmcli", -+ "connection", -+ "up", -+ "filename", -+ "".join( -+ [ -+ "/etc/NetworkManager/system-connections", -+ "/cloud-init-eth1.nmconnection", -+ ] -+ ), -+ ], -+ ), -+ {}, -+ ), - ] - - NETWORKD_BRING_UP_CALL_LIST = [ -@@ -169,9 +230,11 @@ class TestActivatorsBringUp: +@@ -259,9 +254,11 @@ class TestActivatorsBringUp: def test_bring_up_interface( self, m_subp, activator, expected_call_list, available_mocks ): @@ -2283,17 +1389,3 @@ index 3c29e2f7..4525c49c 100644 @patch("cloudinit.subp.subp", return_value=("", "")) def test_bring_up_interfaces( -@@ -208,8 +271,8 @@ IF_UP_DOWN_BRING_DOWN_CALL_LIST = [ - ] - - NETWORK_MANAGER_BRING_DOWN_CALL_LIST = [ -- ((["nmcli", "connection", "down", "eth0"],), {}), -- ((["nmcli", "connection", "down", "eth1"],), {}), -+ ((["nmcli", "device", "disconnect", "eth0"],), {}), -+ ((["nmcli", "device", "disconnect", "eth1"],), {}), - ] - - NETWORKD_BRING_DOWN_CALL_LIST = [ --- -2.31.1 - diff --git a/SOURCES/0013-net-sysconfig-do-not-use-the-highest-autoconnect-pri.patch b/SOURCES/0013-net-sysconfig-do-not-use-the-highest-autoconnect-pri.patch new file mode 100644 index 0000000..cb9b594 --- /dev/null +++ b/SOURCES/0013-net-sysconfig-do-not-use-the-highest-autoconnect-pri.patch @@ -0,0 +1,33 @@ +From 0a2c6b6118ffaf29694b3a51aff3a33298419c50 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Mon, 15 May 2023 19:15:12 +0530 +Subject: [PATCH] net/sysconfig: do not use the highest autoconnect priority + +Using the highest priority is a very big hammer that we may not want to use. We +may want users to override the cloud init generated ifcfg files for custom +configuration of interfaces. If cloud init uses the highest priority, nothing +can beat it. Hence lower the priority to 120 allowing values from 121 to 999 +to be used by users if they want to use a custom interface nm keyfile. + +X-downstream-only: true + +Suggested-by: thaller@redhat.com +fixes: c589da20eb92231 ("Setting highest autoconnect priority for network-scripts") +Signed-off-by: Ani Sinha +--- + cloudinit/net/sysconfig.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py +index b8786fb7..1fe82412 100644 +--- a/cloudinit/net/sysconfig.py ++++ b/cloudinit/net/sysconfig.py +@@ -317,7 +317,7 @@ class Renderer(renderer.Renderer): + "ONBOOT": True, + "USERCTL": False, + "BOOTPROTO": "none", +- "AUTOCONNECT_PRIORITY": 999 ++ "AUTOCONNECT_PRIORITY": 120, + }, + "suse": {"BOOTPROTO": "static", "STARTMODE": "auto"}, + } diff --git a/SOURCES/0014-net-sysconfig-cosmetic-fix-tox-formatting.patch b/SOURCES/0014-net-sysconfig-cosmetic-fix-tox-formatting.patch new file mode 100644 index 0000000..4af002f --- /dev/null +++ b/SOURCES/0014-net-sysconfig-cosmetic-fix-tox-formatting.patch @@ -0,0 +1,43 @@ +From 603ad38bca7735eeb72217b4f169a4b4c42ac092 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Tue, 16 May 2023 16:08:21 +0530 +Subject: [PATCH] net/sysconfig: cosmetic - fix tox formatting + +recommended cloud-init code formatting was not enforced with an older downstream +only change. This change fixes the formatting issue so that tox -e do_format +does not complain. Changes are cosmetic. + +X-downstream-only: true + +fixes: b3b96bff187e9d ("Do not write NM_CONTROLLED=no in generated interface config files") +Signed-off-by: Ani Sinha +--- + cloudinit/net/sysconfig.py | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py +index 1fe82412..fcce3e99 100644 +--- a/cloudinit/net/sysconfig.py ++++ b/cloudinit/net/sysconfig.py +@@ -1025,15 +1025,15 @@ class Renderer(renderer.Renderer): + if sysconfig_path.endswith("network"): + util.ensure_dir(os.path.dirname(sysconfig_path)) + netcfg = [] +- for line in util.load_file(sysconfig_path, quiet=True).split('\n'): +- if 'cloud-init' in line: ++ 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=')): ++ 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']) ++ netcfg.extend([_make_header(), "NETWORKING=yes"]) + if network_state.use_ipv6: + netcfg.append("NETWORKING_IPV6=yes") + netcfg.append("IPV6_AUTOCONF=no") diff --git a/SOURCES/0015-nm-generate-ipv6-stateful-dhcp-config-at-par-with-sy.patch b/SOURCES/0015-nm-generate-ipv6-stateful-dhcp-config-at-par-with-sy.patch new file mode 100644 index 0000000..31e95a8 --- /dev/null +++ b/SOURCES/0015-nm-generate-ipv6-stateful-dhcp-config-at-par-with-sy.patch @@ -0,0 +1,49 @@ +From 58d7574bca2b00d05d090c180f1345a2408cc700 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Mon, 22 May 2023 21:30:01 +0530 +Subject: [PATCH] nm: generate ipv6 stateful dhcp config at par with sysconfig + (#4115) + +The sysconfig renderer sets the following in the ifcfg file for IPV6 stateful +DHCP configuration: + + BOOTPROTO = "dhcp" + DHCPV6C = True + IPV6INIT = True + IPV6_AUTOCONF = False + +This should result in + [ipv6] + method=dhcp + +in the network manager generated keyfile as DHCPV6C is set and +IPV6_AUTOCONF is not set. Unfortunately the network manager renderer +deviates from this and generates: + [ipv6] + method=auto + +in it's rendered keyfile. This change fixes this deviation and sets the +IPV6 dhcp stateful configuration in alignment with what is generated by the +sysconfig renderer. + +RHBZ: 2207716 + +Signed-off-by: Ani Sinha +(cherry picked from commit ea573ba6fc25fe49a6a1a322eeb5259b6238d78b) +--- + cloudinit/net/network_manager.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/cloudinit/net/network_manager.py b/cloudinit/net/network_manager.py +index 53763d15..744c0cbb 100644 +--- a/cloudinit/net/network_manager.py ++++ b/cloudinit/net/network_manager.py +@@ -72,7 +72,7 @@ class NMConnection: + "dhcp6": "auto", + "ipv6_slaac": "auto", + "ipv6_dhcpv6-stateless": "auto", +- "ipv6_dhcpv6-stateful": "auto", ++ "ipv6_dhcpv6-stateful": "dhcp", + "dhcp4": "auto", + "dhcp": "auto", + } diff --git a/SOURCES/0016-network_manager-add-a-method-for-ipv6-static-IP-conf.patch b/SOURCES/0016-network_manager-add-a-method-for-ipv6-static-IP-conf.patch new file mode 100644 index 0000000..be26e61 --- /dev/null +++ b/SOURCES/0016-network_manager-add-a-method-for-ipv6-static-IP-conf.patch @@ -0,0 +1,31 @@ +From 018aa09f049791755dd746b533abb2464b08a92d Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Mon, 22 May 2023 21:33:53 +0530 +Subject: [PATCH] network_manager: add a method for ipv6 static IP + configuration (#4127) + +The static IP configuration for IPv6 in the method_map is missing for +network manager renderer. This is causing cloud-init to generate a keyfile with +IPv6 method as "auto" instead of "manual". This fixes this issue. + +fixes: #4126 +RHBZ: 2196284 + +Signed-off-by: Ani Sinha +(cherry picked from commit 5d440856cb6d2b4c908015fe4eb7227615c17c8b) +--- + cloudinit/net/network_manager.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/cloudinit/net/network_manager.py b/cloudinit/net/network_manager.py +index 744c0cbb..2752f52f 100644 +--- a/cloudinit/net/network_manager.py ++++ b/cloudinit/net/network_manager.py +@@ -69,6 +69,7 @@ class NMConnection: + + method_map = { + "static": "manual", ++ "static6": "manual", + "dhcp6": "auto", + "ipv6_slaac": "auto", + "ipv6_dhcpv6-stateless": "auto", diff --git a/SOURCES/0017-net-sysconfig-enable-sysconfig-renderer-if-network-m.patch b/SOURCES/0017-net-sysconfig-enable-sysconfig-renderer-if-network-m.patch new file mode 100644 index 0000000..ba373ba --- /dev/null +++ b/SOURCES/0017-net-sysconfig-enable-sysconfig-renderer-if-network-m.patch @@ -0,0 +1,62 @@ +From 19adc5a0939fc1804b180333af5486e69d6af0ac Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Mon, 22 May 2023 22:06:28 +0530 +Subject: [PATCH] net/sysconfig: enable sysconfig renderer if network manager + has ifcfg-rh plugin (#4132) + +Some distributions like RHEL does not have ifup and ifdown +scripts that traditionally handled ifcfg-eth* files. Instead RHEL +uses network manager with ifcfg-rh plugin to handle ifcfg +scripts. Therefore, the sysconfig should check for the +existence of ifcfg-rh plugin in addition to checking for the +existence of ifup and ifdown scripts in order to determine if it +can handle ifcfg files. If either the plugin or ifup/ifdown scripts +are present, sysconfig renderer can be enabled. + +fixes: #4131 +RHBZ: 2194050 + +Signed-off-by: Ani Sinha +(cherry picked from commit 009dbf85a72a9077b2267d377b2ff46639fb3def) +--- + cloudinit/net/sysconfig.py | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py +index fcce3e99..f2c7c92c 100644 +--- a/cloudinit/net/sysconfig.py ++++ b/cloudinit/net/sysconfig.py +@@ -1,6 +1,7 @@ + # This file is part of cloud-init. See LICENSE file for license information. + + import copy ++import glob + import io + import os + import re +@@ -1059,7 +1060,25 @@ def _supported_vlan_names(rdev, vid): + def available(target=None): + if not util.system_info()["variant"] in KNOWN_DISTROS: + return False ++ if available_sysconfig(target): ++ return True ++ if available_nm_ifcfg_rh(target): ++ return True ++ return False ++ ++ ++def available_nm_ifcfg_rh(target=None): ++ # The ifcfg-rh plugin of NetworkManager is installed. ++ # NetworkManager can handle the ifcfg files. ++ return glob.glob( ++ subp.target_path( ++ target, ++ "usr/lib*/NetworkManager/*/libnm-settings-plugin-ifcfg-rh.so", ++ ) ++ ) ++ + ++def available_sysconfig(target=None): + expected = ["ifup", "ifdown"] + search = ["/sbin", "/usr/sbin"] + for p in expected: diff --git a/SOURCES/0018-network-manager-Set-higher-autoconnect-priority-for-.patch b/SOURCES/0018-network-manager-Set-higher-autoconnect-priority-for-.patch new file mode 100644 index 0000000..84deac5 --- /dev/null +++ b/SOURCES/0018-network-manager-Set-higher-autoconnect-priority-for-.patch @@ -0,0 +1,401 @@ +From f0cf9e52fd084c23f0552456e3b780b5c9c3313a Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Tue, 23 May 2023 20:38:31 +0530 +Subject: [PATCH] network-manager: Set higher autoconnect priority for nm + keyfiles (#3671) + +cloud init generated keyfiles by network manager renderer for network +interfaces can sometimes conflict with existing keyfiles that are left as an +artifact of an upgrade process or are old user generated keyfiles. When two +such keyfiles are present, the existing keyfile can take precedence over the +cloud init generated keyfile making the later ineffective. Removing the old +keyfile blindly by cloud init would also not be correct since there would be +no way to enforce a different interface configuration if one needs it. + +This change adds an autoconnect-priority value for cloud init generated keyfile +so that the cloud init configuration takes precedence over the existing old +keyfile configuration in the default case. The priority values range from 0 +to 999. We set a value of 120 so that it would be high enough in the default +case and result in cloud init keyfile to take precedence but not too high so +that if the user generated keyfile needs to take precedence, the user can do +so by using a higher value than the one used by cloud init key file, between +the values 121 and 999. + +RHBZ: 2196231 + +Signed-off-by: Ani Sinha +(cherry picked from commit f663e94ac50bc518e694cbd167fdab216fcff029) +--- + cloudinit/net/network_manager.py | 1 + + tests/unittests/cmd/devel/test_net_convert.py | 1 + + .../cloud-init-encc000.2653.nmconnection | 1 + + .../cloud-init-encc000.nmconnection | 1 + + .../cloud-init-zz-all-en.nmconnection | 1 + + .../cloud-init-zz-all-eth.nmconnection | 1 + + tests/unittests/test_net.py | 36 +++++++++++++++++++ + 7 files changed, 42 insertions(+) + +diff --git a/cloudinit/net/network_manager.py b/cloudinit/net/network_manager.py +index 2752f52f..ca216928 100644 +--- a/cloudinit/net/network_manager.py ++++ b/cloudinit/net/network_manager.py +@@ -43,6 +43,7 @@ class NMConnection: + self.config["connection"] = { + "id": f"cloud-init {con_id}", + "uuid": str(uuid.uuid5(CI_NM_UUID, con_id)), ++ "autoconnect-priority": "120", + } + + # This is not actually used anywhere, but may be useful in future +diff --git a/tests/unittests/cmd/devel/test_net_convert.py b/tests/unittests/cmd/devel/test_net_convert.py +index 100aa8de..71654750 100644 +--- a/tests/unittests/cmd/devel/test_net_convert.py ++++ b/tests/unittests/cmd/devel/test_net_convert.py +@@ -74,6 +74,7 @@ SAMPLE_NETWORK_MANAGER_CONTENT = """\ + [connection] + id=cloud-init eth0 + uuid=1dd9a779-d327-56e1-8454-c65e2556c12c ++autoconnect-priority=120 + type=ethernet + interface-name=eth0 + +diff --git a/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-encc000.2653.nmconnection b/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-encc000.2653.nmconnection +index 80483d4f..f44485d2 100644 +--- a/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-encc000.2653.nmconnection ++++ b/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-encc000.2653.nmconnection +@@ -3,6 +3,7 @@ + [connection] + id=cloud-init encc000.2653 + uuid=116aaf19-aabc-50ea-b480-e9aee18bda59 ++autoconnect-priority=120 + type=vlan + interface-name=encc000.2653 + +diff --git a/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-encc000.nmconnection b/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-encc000.nmconnection +index 3368388d..fbdfbc65 100644 +--- a/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-encc000.nmconnection ++++ b/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-encc000.nmconnection +@@ -3,6 +3,7 @@ + [connection] + id=cloud-init encc000 + uuid=f869ebd3-f175-5747-bf02-d0d44d687248 ++autoconnect-priority=120 + type=ethernet + interface-name=encc000 + +diff --git a/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-zz-all-en.nmconnection b/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-zz-all-en.nmconnection +index 16120bc1..dce56c7d 100644 +--- a/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-zz-all-en.nmconnection ++++ b/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-zz-all-en.nmconnection +@@ -3,6 +3,7 @@ + [connection] + id=cloud-init zz-all-en + uuid=159daec9-cba3-5101-85e7-46d831857f43 ++autoconnect-priority=120 + type=ethernet + interface-name=zz-all-en + +diff --git a/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-zz-all-eth.nmconnection b/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-zz-all-eth.nmconnection +index df44d546..ee436bf2 100644 +--- a/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-zz-all-eth.nmconnection ++++ b/tests/unittests/net/artifacts/no_matching_mac/etc/NetworkManager/system-connections/cloud-init-zz-all-eth.nmconnection +@@ -3,6 +3,7 @@ + [connection] + id=cloud-init zz-all-eth + uuid=23a83d8a-d7db-5133-a77b-e68a6ac61ec9 ++autoconnect-priority=120 + type=ethernet + interface-name=zz-all-eth + +diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py +index 0f523ff8..7abe61b9 100644 +--- a/tests/unittests/test_net.py ++++ b/tests/unittests/test_net.py +@@ -631,6 +631,7 @@ dns = none + [connection] + id=cloud-init eth0 + uuid=1dd9a779-d327-56e1-8454-c65e2556c12c ++autoconnect-priority=120 + type=ethernet + + [user] +@@ -1118,6 +1119,7 @@ NETWORK_CONFIGS = { + [connection] + id=cloud-init eth1 + uuid=3c50eb47-7260-5a6d-801d-bd4f587d6b58 ++ autoconnect-priority=120 + type=ethernet + + [user] +@@ -1135,6 +1137,7 @@ NETWORK_CONFIGS = { + [connection] + id=cloud-init eth99 + uuid=b1b88000-1f03-5360-8377-1a2205efffb4 ++ autoconnect-priority=120 + type=ethernet + + [user] +@@ -1234,6 +1237,7 @@ NETWORK_CONFIGS = { + [connection] + id=cloud-init iface0 + uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 ++ autoconnect-priority=120 + type=ethernet + interface-name=iface0 + +@@ -1364,6 +1368,7 @@ NETWORK_CONFIGS = { + [connection] + id=cloud-init iface0 + uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 ++ autoconnect-priority=120 + type=ethernet + interface-name=iface0 + +@@ -1404,6 +1409,7 @@ NETWORK_CONFIGS = { + [connection] + id=cloud-init iface0 + uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 ++ autoconnect-priority=120 + type=ethernet + interface-name=iface0 + +@@ -1504,6 +1510,7 @@ NETWORK_CONFIGS = { + [connection] + id=cloud-init iface0 + uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 ++ autoconnect-priority=120 + type=ethernet + interface-name=iface0 + +@@ -1734,6 +1741,7 @@ NETWORK_CONFIGS = { + [connection] + id=cloud-init iface0 + uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 ++ autoconnect-priority=120 + type=ethernet + interface-name=iface0 + +@@ -1845,6 +1853,7 @@ NETWORK_CONFIGS = { + [connection] + id=cloud-init iface0 + uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 ++ autoconnect-priority=120 + type=ethernet + interface-name=iface0 + +@@ -1967,6 +1976,7 @@ NETWORK_CONFIGS = { + [connection] + id=cloud-init iface0 + uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 ++ autoconnect-priority=120 + type=ethernet + interface-name=iface0 + +@@ -2043,6 +2053,7 @@ NETWORK_CONFIGS = { + [connection] + id=cloud-init iface0 + uuid=8ddfba48-857c-5e86-ac09-1b43eae0bf70 ++ autoconnect-priority=120 + type=ethernet + interface-name=iface0 + +@@ -2507,6 +2518,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + [connection] + id=cloud-init eth3 + uuid=b7e95dda-7746-5bf8-bf33-6e5f3c926790 ++ autoconnect-priority=120 + type=ethernet + slave-type=bridge + master=dee46ce4-af7a-5e7c-aa08-b25533ae9213 +@@ -2526,6 +2538,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + [connection] + id=cloud-init eth5 + uuid=5fda13c7-9942-5e90-a41b-1d043bd725dc ++ autoconnect-priority=120 + type=ethernet + + [user] +@@ -2547,6 +2560,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + [connection] + id=cloud-init ib0 + uuid=11a1dda7-78b4-5529-beba-d9b5f549ad7b ++ autoconnect-priority=120 + type=infiniband + + [user] +@@ -2571,6 +2585,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + [connection] + id=cloud-init bond0.200 + uuid=88984a9c-ff22-5233-9267-86315e0acaa7 ++ autoconnect-priority=120 + type=vlan + interface-name=bond0.200 + +@@ -2594,6 +2609,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + [connection] + id=cloud-init eth0 + uuid=1dd9a779-d327-56e1-8454-c65e2556c12c ++ autoconnect-priority=120 + type=ethernet + + [user] +@@ -2611,6 +2627,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + [connection] + id=cloud-init eth4 + uuid=e27e4959-fb50-5580-b9a4-2073554627b9 ++ autoconnect-priority=120 + type=ethernet + slave-type=bridge + master=dee46ce4-af7a-5e7c-aa08-b25533ae9213 +@@ -2630,6 +2647,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + [connection] + id=cloud-init eth1 + uuid=3c50eb47-7260-5a6d-801d-bd4f587d6b58 ++ autoconnect-priority=120 + type=ethernet + slave-type=bond + master=54317911-f840-516b-a10d-82cb4c1f075c +@@ -2649,6 +2667,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + [connection] + id=cloud-init br0 + uuid=dee46ce4-af7a-5e7c-aa08-b25533ae9213 ++ autoconnect-priority=120 + type=bridge + interface-name=br0 + +@@ -2680,6 +2699,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + [connection] + id=cloud-init eth0.101 + uuid=b5acec5e-db80-5935-8b02-0d5619fc42bf ++ autoconnect-priority=120 + type=vlan + interface-name=eth0.101 + +@@ -2708,6 +2728,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + [connection] + id=cloud-init bond0 + uuid=54317911-f840-516b-a10d-82cb4c1f075c ++ autoconnect-priority=120 + type=bond + interface-name=bond0 + +@@ -2732,6 +2753,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + [connection] + id=cloud-init eth2 + uuid=5559a242-3421-5fdd-896e-9cb8313d5804 ++ autoconnect-priority=120 + type=ethernet + slave-type=bond + master=54317911-f840-516b-a10d-82cb4c1f075c +@@ -3257,6 +3279,7 @@ iface bond0 inet6 static + [connection] + id=cloud-init bond0s0 + uuid=09d0b5b9-67e7-5577-a1af-74d1cf17a71e ++ autoconnect-priority=120 + type=ethernet + slave-type=bond + master=54317911-f840-516b-a10d-82cb4c1f075c +@@ -3276,6 +3299,7 @@ iface bond0 inet6 static + [connection] + id=cloud-init bond0s1 + uuid=4d9aca96-b515-5630-ad83-d13daac7f9d0 ++ autoconnect-priority=120 + type=ethernet + slave-type=bond + master=54317911-f840-516b-a10d-82cb4c1f075c +@@ -3295,6 +3319,7 @@ iface bond0 inet6 static + [connection] + id=cloud-init bond0 + uuid=54317911-f840-516b-a10d-82cb4c1f075c ++ autoconnect-priority=120 + type=bond + interface-name=bond0 + +@@ -3421,6 +3446,7 @@ iface bond0 inet6 static + [connection] + id=cloud-init en0.99 + uuid=f594e2ed-f107-51df-b225-1dc530a5356b ++ autoconnect-priority=120 + type=vlan + interface-name=en0.99 + +@@ -3453,6 +3479,7 @@ iface bond0 inet6 static + [connection] + id=cloud-init en0 + uuid=e0ca478b-8d84-52ab-8fae-628482c629b5 ++ autoconnect-priority=120 + type=ethernet + + [user] +@@ -3580,6 +3607,7 @@ iface bond0 inet6 static + [connection] + id=cloud-init br0 + uuid=dee46ce4-af7a-5e7c-aa08-b25533ae9213 ++ autoconnect-priority=120 + type=bridge + interface-name=br0 + +@@ -3604,6 +3632,7 @@ iface bond0 inet6 static + [connection] + id=cloud-init eth0 + uuid=1dd9a779-d327-56e1-8454-c65e2556c12c ++ autoconnect-priority=120 + type=ethernet + slave-type=bridge + master=dee46ce4-af7a-5e7c-aa08-b25533ae9213 +@@ -3628,6 +3657,7 @@ iface bond0 inet6 static + [connection] + id=cloud-init eth1 + uuid=3c50eb47-7260-5a6d-801d-bd4f587d6b58 ++ autoconnect-priority=120 + type=ethernet + slave-type=bridge + master=dee46ce4-af7a-5e7c-aa08-b25533ae9213 +@@ -3782,6 +3812,7 @@ iface bond0 inet6 static + [connection] + id=cloud-init eth0 + uuid=1dd9a779-d327-56e1-8454-c65e2556c12c ++ autoconnect-priority=120 + type=ethernet + + [user] +@@ -3804,6 +3835,7 @@ iface bond0 inet6 static + [connection] + id=cloud-init eth1 + uuid=3c50eb47-7260-5a6d-801d-bd4f587d6b58 ++ autoconnect-priority=120 + type=ethernet + + [user] +@@ -3826,6 +3858,7 @@ iface bond0 inet6 static + [connection] + id=cloud-init eth2 + uuid=5559a242-3421-5fdd-896e-9cb8313d5804 ++ autoconnect-priority=120 + type=ethernet + + [user] +@@ -5688,6 +5721,7 @@ class TestNetworkManagerRendering(CiTestCase): + [connection] + id=cloud-init eth1000 + uuid=8c517500-0c95-5308-9c8a-3092eebc44eb ++ autoconnect-priority=120 + type=ethernet + + [user] +@@ -5742,6 +5776,7 @@ class TestNetworkManagerRendering(CiTestCase): + [connection] + id=cloud-init interface0 + uuid=8b6862ed-dbd6-5830-93f7-a91451c13828 ++ autoconnect-priority=120 + type=ethernet + + [user] +@@ -5778,6 +5813,7 @@ class TestNetworkManagerRendering(CiTestCase): + [connection] + id=cloud-init eth0 + uuid=1dd9a779-d327-56e1-8454-c65e2556c12c ++ autoconnect-priority=120 + type=ethernet + interface-name=eth0 + diff --git a/SOURCES/0019-Set-default-renderer-as-sysconfig-for-c9s-RHEL-9.patch b/SOURCES/0019-Set-default-renderer-as-sysconfig-for-c9s-RHEL-9.patch new file mode 100644 index 0000000..82c2353 --- /dev/null +++ b/SOURCES/0019-Set-default-renderer-as-sysconfig-for-c9s-RHEL-9.patch @@ -0,0 +1,42 @@ +From 5394e28e896e9d18db6d359190bfb58dcbdb2646 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Tue, 23 May 2023 21:15:30 +0530 +Subject: [PATCH] Set default renderer as sysconfig for c9s/RHEL 9 + +Currently, network manager is disabled on c9s and RHEL 9 and therefore +sysconfig is used as the primary renderer for network configuration on those +distribution flavors. We do not want to change this for c9s or RHEL 9 even when +network-manager renderer is re-enabled. NM was re-enabled with the following +commit: +5822f72230a58d ("Revert "Revert "Add native NetworkManager support (#1224)""") + +This change bumps up the priority for sysconfig renderer so that it is used as +the primary renderer on c9s/RHEL 9 and other downstream distributions derived +from them. For c10s or RHEL 10, we might revert this change so that +network-manager again becomes the primary renderer for those distributions. + +X-downstream-only: true + +fixes: 0b0632f6c0 ("Revert "Manual revert "Use Network-Manager and Netplan as default renderers for RHEL and Fedora (#1465)") +fixes: 7703aa98b89 ("Use Network-Manager and Netplan as default renderers for RHEL and Fedora (#1465)") + +RHBZ:2209349 + +Signed-off-by: Ani Sinha +--- + config/cloud.cfg.tmpl | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl +index 7238c102..22c6654c 100644 +--- a/config/cloud.cfg.tmpl ++++ b/config/cloud.cfg.tmpl +@@ -383,7 +383,7 @@ system_info: + renderers: ['freebsd'] + {% elif variant in ["fedora"] or is_rhel %} + network: +- renderers: ['netplan', 'network-manager', 'networkd', 'sysconfig', 'eni'] ++ renderers: ['sysconfig', 'eni', 'netplan', 'network-manager', 'networkd'] + {% elif variant == "openmandriva" %} + network: + renderers: ['network-manager', 'networkd'] diff --git a/SOURCES/0020-Revert-Set-default-renderer-as-sysconfig-for-c9s-RHE.patch b/SOURCES/0020-Revert-Set-default-renderer-as-sysconfig-for-c9s-RHE.patch new file mode 100644 index 0000000..b4c93c1 --- /dev/null +++ b/SOURCES/0020-Revert-Set-default-renderer-as-sysconfig-for-c9s-RHE.patch @@ -0,0 +1,25 @@ +From 86dd9b0e215a40e60a6c48401a9c04215e10cdea Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Thu, 8 Jun 2023 10:19:49 +0530 +Subject: [PATCH] Revert "Set default renderer as sysconfig for c9s/RHEL 9" + +This reverts commit 5394e28e896e9d18db6d359190bfb58dcbdb2646. + +Revert this downstream-only patch and replace it with the upstream patch. +--- + config/cloud.cfg.tmpl | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl +index 22c6654c..7238c102 100644 +--- a/config/cloud.cfg.tmpl ++++ b/config/cloud.cfg.tmpl +@@ -383,7 +383,7 @@ system_info: + renderers: ['freebsd'] + {% elif variant in ["fedora"] or is_rhel %} + network: +- renderers: ['sysconfig', 'eni', 'netplan', 'network-manager', 'networkd'] ++ renderers: ['netplan', 'network-manager', 'networkd', 'sysconfig', 'eni'] + {% elif variant == "openmandriva" %} + network: + renderers: ['network-manager', 'networkd'] diff --git a/SOURCES/0021-Set-default-renderer-as-sysconfig-for-centos-rhel-41.patch b/SOURCES/0021-Set-default-renderer-as-sysconfig-for-centos-rhel-41.patch new file mode 100644 index 0000000..46f0f79 --- /dev/null +++ b/SOURCES/0021-Set-default-renderer-as-sysconfig-for-centos-rhel-41.patch @@ -0,0 +1,35 @@ +From fd4f6d94e09ed97a4dd6aba3284d9156c16c483b Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Thu, 8 Jun 2023 03:29:13 +0530 +Subject: [PATCH] Set default renderer as sysconfig for centos/rhel (#4165) + +Currently, network manager is disabled on c9s and therefore sysconfig is used as the primary renderer for network configuration. We do not want to change this for c9s even when network-manager renderer is re-enabled as it would mean a big behaviour change for cloud-init in the centos 9 stream. + +This change bumps up the priority for sysconfig renderer so that it is used as the primary renderer on c9s and other downstream distributions derived from it. In the next major centos stream release, we may use network manager as the default renderer and make changes accordingly. + +RHBZ: 2209349 + +Signed-off-by: Ani Sinha +(cherry picked from commit a1f375095bd0ac8628c4fdc79538dc177bb9ff99) +--- + config/cloud.cfg.tmpl | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl +index 7238c102..020340f9 100644 +--- a/config/cloud.cfg.tmpl ++++ b/config/cloud.cfg.tmpl +@@ -381,9 +381,12 @@ system_info: + {% elif variant in ["dragonfly"] %} + network: + renderers: ['freebsd'] +-{% elif variant in ["fedora"] or is_rhel %} ++{% elif variant in ["fedora"] %} + network: + renderers: ['netplan', 'network-manager', 'networkd', 'sysconfig', 'eni'] ++{% elif is_rhel %} ++ network: ++ renderers: ['sysconfig', 'eni', 'netplan', 'network-manager', 'networkd' ] + {% elif variant == "openmandriva" %} + network: + renderers: ['network-manager', 'networkd'] diff --git a/SOURCES/0022-test-fixes-update-tests-to-reflect-AUTOCONNECT_PRIOR.patch b/SOURCES/0022-test-fixes-update-tests-to-reflect-AUTOCONNECT_PRIOR.patch new file mode 100644 index 0000000..eb85d1a --- /dev/null +++ b/SOURCES/0022-test-fixes-update-tests-to-reflect-AUTOCONNECT_PRIOR.patch @@ -0,0 +1,509 @@ +From 908387bc0a73ae3431c0ad90f83e6a4a4e902edb Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Fri, 23 Jun 2023 15:47:09 +0530 +Subject: [PATCH] test fixes: update tests to reflect AUTOCONNECT_PRIORITY + setting + +X-downstream-only: true +fixes: 0a2c6b6118ff ("net/sysconfig: do not use the highest autoconnect priority") +fixes: c589da20eb92 ("Setting highest autoconnect priority for network-scripts") + +Signed-off-by: Ani Sinha +--- + tests/unittests/cmd/devel/test_net_convert.py | 1 + + tests/unittests/distros/test_netconfig.py | 8 +++ + tests/unittests/test_net.py | 51 +++++++++++++++++++ + 3 files changed, 60 insertions(+) + +diff --git a/tests/unittests/cmd/devel/test_net_convert.py b/tests/unittests/cmd/devel/test_net_convert.py +index 71654750..43e879f7 100644 +--- a/tests/unittests/cmd/devel/test_net_convert.py ++++ b/tests/unittests/cmd/devel/test_net_convert.py +@@ -60,6 +60,7 @@ DHCP=ipv4 + SAMPLE_SYSCONFIG_CONTENT = """\ + # Created by cloud-init on instance boot automatically, do not edit. + # ++AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=eth0 + NM_CONTROLLED=no +diff --git a/tests/unittests/distros/test_netconfig.py b/tests/unittests/distros/test_netconfig.py +index b1c89ce3..eaf723c8 100644 +--- a/tests/unittests/distros/test_netconfig.py ++++ b/tests/unittests/distros/test_netconfig.py +@@ -717,6 +717,7 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + expected_cfgs = { + self.ifcfg_path("eth0"): dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEFROUTE=yes + DEVICE=eth0 +@@ -731,6 +732,7 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + ), + self.ifcfg_path("eth1"): dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=eth1 + NM_CONTROLLED=no +@@ -756,6 +758,7 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + expected_cfgs = { + self.ifcfg_path("eth0"): dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEFROUTE=yes + DEVICE=eth0 +@@ -772,6 +775,7 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + ), + self.ifcfg_path("eth1"): dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=eth1 + NM_CONTROLLED=no +@@ -816,6 +820,7 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + expected_cfgs = { + self.ifcfg_path("eth0"): dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=eth0 + HWADDR=00:16:3e:60:7c:df +@@ -829,6 +834,7 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + ), + self.ifcfg_path("infra0"): dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=infra0 + IPADDR=10.0.1.2 +@@ -865,6 +871,7 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + expected_cfgs = { + self.ifcfg_path("eth0"): dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=eth0 + IPADDR=192.10.1.2 +@@ -877,6 +884,7 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + ), + self.ifcfg_path("eth0.1001"): dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=eth0.1001 + IPADDR=10.0.1.2 +diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py +index 7abe61b9..1261840b 100644 +--- a/tests/unittests/test_net.py ++++ b/tests/unittests/test_net.py +@@ -578,6 +578,7 @@ dns = none + """ + # Created by cloud-init on instance boot automatically, do not edit. + # ++AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEFROUTE=yes + DEVICE=eth0 +@@ -740,6 +741,7 @@ dns = none + """ + # Created by cloud-init on instance boot automatically, do not edit. + # ++AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEFROUTE=yes + DEVICE=eth0 +@@ -897,6 +899,7 @@ dns = none + """ + # Created by cloud-init on instance boot automatically, do not edit. + # ++AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEFROUTE=yes + DEVICE=eth0 +@@ -1085,6 +1088,7 @@ NETWORK_CONFIGS = { + "expected_sysconfig_rhel": { + "ifcfg-eth1": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=eth1 + HWADDR=cf:d6:af:48:e8:80 +@@ -1094,6 +1098,7 @@ NETWORK_CONFIGS = { + ), + "ifcfg-eth99": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEFROUTE=yes + DEVICE=eth99 +@@ -1344,6 +1349,7 @@ NETWORK_CONFIGS = { + "expected_sysconfig_rhel": { + "ifcfg-iface0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=iface0 + IPADDR=192.168.14.2 +@@ -1490,6 +1496,7 @@ NETWORK_CONFIGS = { + "expected_sysconfig_rhel": { + "ifcfg-iface0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=iface0 + DHCPV6C=yes +@@ -1580,6 +1587,7 @@ NETWORK_CONFIGS = { + "expected_sysconfig_rhel": { + "ifcfg-iface0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=iface0 + DHCPV6C=yes +@@ -1656,6 +1664,7 @@ NETWORK_CONFIGS = { + "expected_sysconfig_rhel": { + "ifcfg-iface0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=iface0 + DHCPV6C=yes +@@ -1721,6 +1730,7 @@ NETWORK_CONFIGS = { + "expected_sysconfig_rhel": { + "ifcfg-iface0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=iface0 + IPV6_AUTOCONF=yes +@@ -1774,6 +1784,7 @@ NETWORK_CONFIGS = { + "expected_sysconfig_rhel": { + "ifcfg-iface0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=iface0 + IPV6ADDR=2001:1::1/64 +@@ -1831,6 +1842,7 @@ NETWORK_CONFIGS = { + "expected_sysconfig_rhel": { + "ifcfg-iface0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=iface0 + DHCPV6C=yes +@@ -1913,6 +1925,7 @@ NETWORK_CONFIGS = { + "expected_sysconfig_rhel": { + "ifcfg-iface0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=iface0 + DHCPV6C=yes +@@ -1959,6 +1972,7 @@ NETWORK_CONFIGS = { + "expected_sysconfig_rhel": { + "ifcfg-iface0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=iface0 + NM_CONTROLLED=no +@@ -2035,6 +2049,7 @@ NETWORK_CONFIGS = { + "expected_sysconfig_rhel": { + "ifcfg-iface0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=iface0 + ETHTOOL_OPTS="wol g" +@@ -2371,6 +2386,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + "expected_sysconfig_rhel": { + "ifcfg-bond0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BONDING_MASTER=yes + BONDING_OPTS="mode=active-backup """ + """xmit_hash_policy=layer3+4 """ +@@ -2388,6 +2404,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + ), + "ifcfg-bond0.200": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=bond0.200 + DHCLIENT_SET_DEFAULT_ROUTE=no +@@ -2399,6 +2416,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + "ifcfg-br0": textwrap.dedent( + """\ + AGEING=250 ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEFROUTE=yes + DEVICE=br0 +@@ -2418,6 +2436,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + ), + "ifcfg-eth0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=eth0 + HWADDR=c0:d6:9f:2c:e8:80 +@@ -2427,6 +2446,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + ), + "ifcfg-eth0.101": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEFROUTE=yes + DEVICE=eth0.101 +@@ -2446,6 +2466,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + ), + "ifcfg-eth1": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=eth1 + HWADDR=aa:d6:9f:2c:e8:80 +@@ -2457,6 +2478,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + ), + "ifcfg-eth2": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=eth2 + HWADDR=c0:bb:9f:2c:e8:80 +@@ -2468,6 +2490,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + ), + "ifcfg-eth3": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + BRIDGE=br0 + DEVICE=eth3 +@@ -2478,6 +2501,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + ), + "ifcfg-eth4": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + BRIDGE=br0 + DEVICE=eth4 +@@ -2488,6 +2512,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + ), + "ifcfg-eth5": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=eth5 + DHCLIENT_SET_DEFAULT_ROUTE=no +@@ -2498,6 +2523,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true + ), + "ifcfg-ib0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=ib0 + HWADDR=a0:00:02:20:fe:80:00:00:00:00:00:00:ec:0d:9a:03:00:15:e2:c1 +@@ -3203,6 +3229,7 @@ iface bond0 inet6 static + "expected_sysconfig_rhel": { + "ifcfg-bond0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BONDING_MASTER=yes + BONDING_OPTS="mode=active-backup xmit_hash_policy=layer3+4 """ + """miimon=100 num_grat_arp=5 """ +@@ -3233,6 +3260,7 @@ iface bond0 inet6 static + ), + "ifcfg-bond0s0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=bond0s0 + HWADDR=aa:bb:cc:dd:e8:00 +@@ -3260,6 +3288,7 @@ iface bond0 inet6 static + ), + "ifcfg-bond0s1": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=bond0s1 + HWADDR=aa:bb:cc:dd:e8:01 +@@ -3409,6 +3438,7 @@ iface bond0 inet6 static + "expected_sysconfig_rhel": { + "ifcfg-en0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=en0 + HWADDR=aa:bb:cc:dd:e8:00 +@@ -3418,6 +3448,7 @@ iface bond0 inet6 static + ), + "ifcfg-en0.99": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEFROUTE=yes + DEVICE=en0.99 +@@ -3555,6 +3586,7 @@ iface bond0 inet6 static + "expected_sysconfig_rhel": { + "ifcfg-br0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=br0 + IPADDR=192.168.2.2 +@@ -3568,6 +3600,7 @@ iface bond0 inet6 static + ), + "ifcfg-eth0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + BRIDGE=br0 + DEVICE=eth0 +@@ -3584,6 +3617,7 @@ iface bond0 inet6 static + ), + "ifcfg-eth1": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + BRIDGE=br0 + DEVICE=eth1 +@@ -3772,6 +3806,7 @@ iface bond0 inet6 static + "expected_sysconfig_rhel": { + "ifcfg-eth0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=eth0 + HWADDR=52:54:00:12:34:00 +@@ -3784,6 +3819,7 @@ iface bond0 inet6 static + ), + "ifcfg-eth1": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=eth1 + HWADDR=52:54:00:12:34:aa +@@ -3795,6 +3831,7 @@ iface bond0 inet6 static + ), + "ifcfg-eth2": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=eth2 + HWADDR=52:54:00:12:34:ff +@@ -3879,6 +3916,7 @@ iface bond0 inet6 static + "expected_sysconfig_rhel": { + "ifcfg-eth0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=eth0 + HWADDR=cf:d6:af:48:e8:80 +@@ -4474,6 +4512,7 @@ class TestRhelSysConfigRendering(CiTestCase): + expected_content = """ + # Created by cloud-init on instance boot automatically, do not edit. + # ++AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=eth1000 + HWADDR=07-1c-c6-75-a4-be +@@ -4681,6 +4720,7 @@ USERCTL=no + expected = """\ + # Created by cloud-init on instance boot automatically, do not edit. + # ++AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEFROUTE=yes + DEVICE=interface0 +@@ -4710,6 +4750,7 @@ USERCTL=no + expected_i1 = """\ + # Created by cloud-init on instance boot automatically, do not edit. + # ++AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEFROUTE=yes + DEVICE=eth0 +@@ -4727,6 +4768,7 @@ USERCTL=no + expected_i2 = """\ + # Created by cloud-init on instance boot automatically, do not edit. + # ++AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=eth1 + DHCLIENT_SET_DEFAULT_ROUTE=no +@@ -4755,6 +4797,7 @@ USERCTL=no + expected = """\ + # Created by cloud-init on instance boot automatically, do not edit. + # ++AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=eth0 + ONBOOT=yes +@@ -4968,6 +5011,7 @@ USERCTL=no + "expected_sysconfig": { + "ifcfg-ens3": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEFROUTE=yes + DEVICE=ens3 +@@ -5013,6 +5057,7 @@ USERCTL=no + expected = { + "ifcfg-eno1": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=eno1 + NM_CONTROLLED=no +@@ -5023,6 +5068,7 @@ USERCTL=no + ), + "ifcfg-eno1.1000": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=eno1.1000 + IPADDR=192.6.1.9 +@@ -5056,6 +5102,7 @@ USERCTL=no + expected = { + "ifcfg-bond0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BONDING_MASTER=yes + BONDING_SLAVE0=enp0s0 + BONDING_SLAVE1=enp0s1 +@@ -5072,6 +5119,7 @@ USERCTL=no + ), + "ifcfg-enp0s0": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BONDING_MASTER=yes + BOOTPROTO=none + DEVICE=enp0s0 +@@ -5085,6 +5133,7 @@ USERCTL=no + ), + "ifcfg-enp0s1": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BONDING_MASTER=yes + BOOTPROTO=none + DEVICE=enp0s1 +@@ -5116,6 +5165,7 @@ USERCTL=no + expected = { + "ifcfg-eno1": textwrap.dedent( + """\ ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=eno1 + HWADDR=07-1c-c6-75-a4-be +@@ -5195,6 +5245,7 @@ USERCTL=no + """\ + # Created by cloud-init on instance boot automatically, do not edit. + # ++ AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEFROUTE=yes + DEVICE=eth0 diff --git a/SOURCES/0023-test-fixes-remove-NM_CONTROLLED-no-from-tests.patch b/SOURCES/0023-test-fixes-remove-NM_CONTROLLED-no-from-tests.patch new file mode 100644 index 0000000..f9d3362 --- /dev/null +++ b/SOURCES/0023-test-fixes-remove-NM_CONTROLLED-no-from-tests.patch @@ -0,0 +1,283 @@ +From 9eb7ef217eb03131904fb6e0c692130126334f52 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Fri, 23 Jun 2023 16:54:24 +0530 +Subject: [PATCH] test fixes: remove NM_CONTROLLED=no from tests + +X-downstream-only: true +fixes: b3b96bff187e9 ("Do not write NM_CONTROLLED=no in generated interface config files") + +Signed-off-by: Ani Sinha +--- + tests/unittests/cmd/devel/test_net_convert.py | 1 - + tests/unittests/distros/test_netconfig.py | 8 ------- + tests/unittests/test_net.py | 23 ------------------- + 3 files changed, 32 deletions(-) + +diff --git a/tests/unittests/cmd/devel/test_net_convert.py b/tests/unittests/cmd/devel/test_net_convert.py +index 43e879f7..082e9656 100644 +--- a/tests/unittests/cmd/devel/test_net_convert.py ++++ b/tests/unittests/cmd/devel/test_net_convert.py +@@ -63,7 +63,6 @@ SAMPLE_SYSCONFIG_CONTENT = """\ + AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=eth0 +-NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +diff --git a/tests/unittests/distros/test_netconfig.py b/tests/unittests/distros/test_netconfig.py +index eaf723c8..7ac8182a 100644 +--- a/tests/unittests/distros/test_netconfig.py ++++ b/tests/unittests/distros/test_netconfig.py +@@ -724,7 +724,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + GATEWAY=192.168.1.254 + IPADDR=192.168.1.5 + NETMASK=255.255.255.0 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -735,7 +734,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=eth1 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -767,7 +765,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + IPV6_AUTOCONF=no + IPV6_DEFAULTGW=2607:f0d0:1002:0011::1 + IPV6_FORCE_ACCEPT_RA=no +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -778,7 +775,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=eth1 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -826,7 +822,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + HWADDR=00:16:3e:60:7c:df + IPADDR=192.10.1.2 + NETMASK=255.255.255.0 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -839,7 +834,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + DEVICE=infra0 + IPADDR=10.0.1.2 + NETMASK=255.255.0.0 +- NM_CONTROLLED=no + ONBOOT=yes + PHYSDEV=eth0 + USERCTL=no +@@ -876,7 +870,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + DEVICE=eth0 + IPADDR=192.10.1.2 + NETMASK=255.255.255.0 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -889,7 +882,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): + DEVICE=eth0.1001 + IPADDR=10.0.1.2 + NETMASK=255.255.0.0 +- NM_CONTROLLED=no + ONBOOT=yes + PHYSDEV=eth0 + USERCTL=no +diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py +index 1261840b..fd656a57 100644 +--- a/tests/unittests/test_net.py ++++ b/tests/unittests/test_net.py +@@ -1502,7 +1502,6 @@ NETWORK_CONFIGS = { + DHCPV6C=yes + IPV6INIT=yes + DEVICE=iface0 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -1594,7 +1593,6 @@ NETWORK_CONFIGS = { + IPV6INIT=yes + IPV6_FORCE_ACCEPT_RA=yes + DEVICE=iface0 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -1671,7 +1669,6 @@ NETWORK_CONFIGS = { + IPV6INIT=yes + IPV6_FORCE_ACCEPT_RA=no + DEVICE=iface0 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -1736,7 +1733,6 @@ NETWORK_CONFIGS = { + IPV6_AUTOCONF=yes + IPV6INIT=yes + DEVICE=iface0 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -1792,7 +1788,6 @@ NETWORK_CONFIGS = { + IPV6_AUTOCONF=no + IPV6_FORCE_ACCEPT_RA=no + DEVICE=iface0 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -1850,7 +1845,6 @@ NETWORK_CONFIGS = { + IPV6_AUTOCONF=yes + IPV6INIT=yes + DEVICE=iface0 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -1933,7 +1927,6 @@ NETWORK_CONFIGS = { + IPV6_AUTOCONF=no + IPV6_FORCE_ACCEPT_RA=yes + DEVICE=iface0 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -1975,7 +1968,6 @@ NETWORK_CONFIGS = { + AUTOCONNECT_PRIORITY=120 + BOOTPROTO=dhcp + DEVICE=iface0 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -2053,7 +2045,6 @@ NETWORK_CONFIGS = { + BOOTPROTO=dhcp + DEVICE=iface0 + ETHTOOL_OPTS="wol g" +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -2530,7 +2521,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 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=InfiniBand + USERCTL=no""" +@@ -3609,7 +3599,6 @@ iface bond0 inet6 static + IPV6INIT=yes + IPV6_AUTOCONF=no + IPV6_FORCE_ACCEPT_RA=no +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -3626,7 +3615,6 @@ iface bond0 inet6 static + IPV6INIT=yes + IPV6_AUTOCONF=no + IPV6_FORCE_ACCEPT_RA=no +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -3920,7 +3908,6 @@ iface bond0 inet6 static + BOOTPROTO=none + DEVICE=eth0 + HWADDR=cf:d6:af:48:e8:80 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no""" +@@ -4759,7 +4746,6 @@ HWADDR=fa:16:3e:25:b4:59 + IPADDR=51.68.89.122 + MTU=1500 + NETMASK=255.255.240.0 +-NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -4774,7 +4760,6 @@ DEVICE=eth1 + DHCLIENT_SET_DEFAULT_ROUTE=no + HWADDR=fa:16:3e:b1:ca:29 + MTU=9000 +-NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -5027,7 +5012,6 @@ USERCTL=no + IPV6_FORCE_ACCEPT_RA=no + IPV6_DEFAULTGW=2001:db8::1 + NETMASK=255.255.255.0 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -5060,7 +5044,6 @@ USERCTL=no + AUTOCONNECT_PRIORITY=120 + BOOTPROTO=none + DEVICE=eno1 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -5074,7 +5057,6 @@ USERCTL=no + IPADDR=192.6.1.9 + MTU=1495 + NETMASK=255.255.255.0 +- NM_CONTROLLED=no + ONBOOT=yes + PHYSDEV=eno1 + USERCTL=no +@@ -5111,7 +5093,6 @@ USERCTL=no + IPADDR=10.101.8.65 + MTU=1334 + NETMASK=255.255.255.192 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Bond + USERCTL=no +@@ -5124,7 +5105,6 @@ USERCTL=no + BOOTPROTO=none + DEVICE=enp0s0 + MASTER=bond0 +- NM_CONTROLLED=no + ONBOOT=yes + SLAVE=yes + TYPE=Bond +@@ -5138,7 +5118,6 @@ USERCTL=no + BOOTPROTO=none + DEVICE=enp0s1 + MASTER=bond0 +- NM_CONTROLLED=no + ONBOOT=yes + SLAVE=yes + TYPE=Bond +@@ -5170,7 +5149,6 @@ USERCTL=no + DEVICE=eno1 + HWADDR=07-1c-c6-75-a4-be + METRIC=100 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no +@@ -5262,7 +5240,6 @@ USERCTL=no + IPV6_FORCE_ACCEPT_RA=no + MTU=1400 + NETMASK=255.255.248.0 +- NM_CONTROLLED=no + ONBOOT=yes + TYPE=Ethernet + USERCTL=no diff --git a/SOURCES/0024-Revert-limit-permissions-on-def_log_file.patch b/SOURCES/0024-Revert-limit-permissions-on-def_log_file.patch new file mode 100644 index 0000000..1b0e024 --- /dev/null +++ b/SOURCES/0024-Revert-limit-permissions-on-def_log_file.patch @@ -0,0 +1,58 @@ +From d39cd4de3ce41b1a1727185f2e57ec27190c23cb Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Tue, 4 Jul 2023 13:58:27 +0530 +Subject: [PATCH] Revert "limit permissions on def_log_file" + +This reverts commit dfff374f66904e84fb07ca157ba010fac6b5f1de. + +This commit seems useless and does not effectively change permission of the +log file. Remove it. +--- + cloudinit/settings.py | 1 - + cloudinit/stages.py | 1 - + doc/examples/cloud-config.txt | 4 ---- + 3 files changed, 6 deletions(-) + +diff --git a/cloudinit/settings.py b/cloudinit/settings.py +index 3d541141..edbb217d 100644 +--- a/cloudinit/settings.py ++++ b/cloudinit/settings.py +@@ -52,7 +52,6 @@ CFG_BUILTIN = { + "None", + ], + "def_log_file": "/var/log/cloud-init.log", +- "def_log_file_mode": 0o600, + "log_cfgs": [], + "mount_default_fields": [None, None, "auto", "defaults,nofail", "0", "2"], + "syslog_fix_perms": [], +diff --git a/cloudinit/stages.py b/cloudinit/stages.py +index 1326d205..21f30a1f 100644 +--- a/cloudinit/stages.py ++++ b/cloudinit/stages.py +@@ -202,7 +202,6 @@ class Init: + def _initialize_filesystem(self): + util.ensure_dirs(self._initial_subdirs()) + log_file = util.get_cfg_option_str(self.cfg, "def_log_file") +- log_file_mode = util.get_cfg_option_int(self.cfg, "def_log_file_mode") + if log_file: + # At this point the log file should have already been created + # in the setupLogging function of log.py +diff --git a/doc/examples/cloud-config.txt b/doc/examples/cloud-config.txt +index b6d16c9c..15d788f3 100644 +--- a/doc/examples/cloud-config.txt ++++ b/doc/examples/cloud-config.txt +@@ -383,14 +383,10 @@ timezone: US/Eastern + # if syslog_fix_perms is a list, it will iterate through and use the + # first pair that does not raise error. + # +-# 'def_log_file' will be created with mode 'def_log_file_mode', which +-# is specified as a numeric value and defaults to 0600. +-# + # the default values are '/var/log/cloud-init.log' and 'syslog:adm' + # the value of 'def_log_file' should match what is configured in logging + # if either is empty, then no change of ownership will be done + def_log_file: /var/log/my-logging-file.log +-def_log_file_mode: 0600 + syslog_fix_perms: syslog:root + + # you can set passwords for a user or multiple users diff --git a/SOURCES/0025-test-fixes-changes-to-apply-RHEL-specific-config-set.patch b/SOURCES/0025-test-fixes-changes-to-apply-RHEL-specific-config-set.patch new file mode 100644 index 0000000..aaefb26 --- /dev/null +++ b/SOURCES/0025-test-fixes-changes-to-apply-RHEL-specific-config-set.patch @@ -0,0 +1,43 @@ +From f1ccdbdb6c662ce67b4af74e0433a59f099d784a Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Fri, 23 Jun 2023 17:54:04 +0530 +Subject: [PATCH] test fixes: changes to apply RHEL specific config settings to + tests + +X-downstream-only: true +fixes: c4d66915520554adedff9b ("Add initial redhat changes") +fixes: dfff374f66904e84fb07ca ("limit permissions on def_log_file") + +Signed-off-by: Ani Sinha +--- + tests/unittests/cmd/test_main.py | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/tests/unittests/cmd/test_main.py b/tests/unittests/cmd/test_main.py +index e9ad0bb8..5d61aa2c 100644 +--- a/tests/unittests/cmd/test_main.py ++++ b/tests/unittests/cmd/test_main.py +@@ -119,14 +119,17 @@ class TestMain(FilesystemMockingTestCase): + { + "def_log_file": "/var/log/cloud-init.log", + "log_cfgs": [], +- "syslog_fix_perms": [ +- "syslog:adm", +- "root:adm", +- "root:wheel", +- "root:root", +- ], + "vendor_data": {"enabled": True, "prefix": []}, + "vendor_data2": {"enabled": True, "prefix": []}, ++ "syslog_fix_perms": [], ++ "mount_default_fields": [ ++ None, ++ None, ++ "auto", ++ "defaults,nofail", ++ "0", ++ "2", ++ ], + } + ) + updated_cfg.pop("system_info") diff --git a/SOURCES/0026-Enable-SUSE-based-distros-for-ca-handling-2036.patch b/SOURCES/0026-Enable-SUSE-based-distros-for-ca-handling-2036.patch new file mode 100644 index 0000000..2b2ca7d --- /dev/null +++ b/SOURCES/0026-Enable-SUSE-based-distros-for-ca-handling-2036.patch @@ -0,0 +1,90 @@ +From 7a530e186e791858bf70accd2fab80dd9b43ee7e Mon Sep 17 00:00:00 2001 +From: Robert Schweikert +Date: Thu, 23 Feb 2023 16:43:56 -0500 +Subject: [PATCH] Enable SUSE based distros for ca handling (#2036) + +CA handling in the configuration module was previously not supported +for SUSE based distros. Enable this functionality by creating the +necessary configuration settings. + +Secondly update the test such that it does not bleed through to the +test system. + +(cherry picked from commit 46fcd03187d70f405c748f7a6cfdb02ecb8c6ee7) +Signed-off-by: Ani Sinha +--- + cloudinit/config/cc_ca_certs.py | 31 +++++++++++++++++++++- + tests/unittests/config/test_cc_ca_certs.py | 2 ++ + 2 files changed, 32 insertions(+), 1 deletion(-) + +diff --git a/cloudinit/config/cc_ca_certs.py b/cloudinit/config/cc_ca_certs.py +index 169b0e18..51b8577c 100644 +--- a/cloudinit/config/cc_ca_certs.py ++++ b/cloudinit/config/cc_ca_certs.py +@@ -32,8 +32,25 @@ DISTRO_OVERRIDES = { + "ca_cert_config": None, + "ca_cert_update_cmd": ["update-ca-trust"], + }, ++ "opensuse": { ++ "ca_cert_path": "/etc/pki/trust/", ++ "ca_cert_local_path": "/usr/share/pki/trust/", ++ "ca_cert_filename": "anchors/cloud-init-ca-cert-{cert_index}.crt", ++ "ca_cert_config": None, ++ "ca_cert_update_cmd": ["update-ca-certificates"], ++ }, + } + ++for distro in ( ++ "opensuse-microos", ++ "opensuse-tumbleweed", ++ "opensuse-leap", ++ "sle_hpc", ++ "sle-micro", ++ "sles", ++): ++ DISTRO_OVERRIDES[distro] = DISTRO_OVERRIDES["opensuse"] ++ + MODULE_DESCRIPTION = """\ + This module adds CA certificates to the system's CA store and updates any + related files using the appropriate OS-specific utility. The default CA +@@ -48,7 +65,19 @@ configuration option ``remove_defaults``. + Alpine Linux requires the ca-certificates package to be installed in + order to provide the ``update-ca-certificates`` command. + """ +-distros = ["alpine", "debian", "rhel", "ubuntu"] ++distros = [ ++ "alpine", ++ "debian", ++ "rhel", ++ "opensuse", ++ "opensuse-microos", ++ "opensuse-tumbleweed", ++ "opensuse-leap", ++ "sle_hpc", ++ "sle-micro", ++ "sles", ++ "ubuntu", ++] + + meta: MetaSchema = { + "id": "cc_ca_certs", +diff --git a/tests/unittests/config/test_cc_ca_certs.py b/tests/unittests/config/test_cc_ca_certs.py +index 19e5d422..6db17485 100644 +--- a/tests/unittests/config/test_cc_ca_certs.py ++++ b/tests/unittests/config/test_cc_ca_certs.py +@@ -311,6 +311,7 @@ class TestRemoveDefaultCaCerts(TestCase): + "cloud_dir": tmpdir, + } + ) ++ self.add_patch("cloudinit.config.cc_ca_certs.os.stat", "m_stat") + + def test_commands(self): + ca_certs_content = "# line1\nline2\nline3\n" +@@ -318,6 +319,7 @@ class TestRemoveDefaultCaCerts(TestCase): + "# line1\n# Modified by cloud-init to deselect certs due to" + " user-data\n!line2\n!line3\n" + ) ++ self.m_stat.return_value.st_size = 1 + + for distro_name in cc_ca_certs.distros: + conf = cc_ca_certs._distro_ca_certs_configs(distro_name) diff --git a/SOURCES/0027-Handle-non-existent-ca-cert-config-situation-2073.patch b/SOURCES/0027-Handle-non-existent-ca-cert-config-situation-2073.patch new file mode 100644 index 0000000..ecdf8ca --- /dev/null +++ b/SOURCES/0027-Handle-non-existent-ca-cert-config-situation-2073.patch @@ -0,0 +1,85 @@ +From add770c442088c0915bdefad2a7438f9a38596c5 Mon Sep 17 00:00:00 2001 +From: Shreenidhi Shedi <53473811+sshedi@users.noreply.github.com> +Date: Fri, 17 Mar 2023 03:01:22 +0530 +Subject: [PATCH] Handle non existent ca-cert-config situation (#2073) + +Currently if a cert file doesn't exist, cc_ca_certs module crashes +This fix makes it possible to handle it gracefully. + +Also, out_lines variable may not be available if os.stat returns 0. +This issue is also taken care of. + +Added tests for the same. + +(cherry picked from commit 3634678465e7b8f8608bcb9a1f5773ae7837cbe9) +Signed-off-by: Ani Sinha +--- + cloudinit/config/cc_ca_certs.py | 19 +++++++++++++------ + tests/unittests/config/test_cc_ca_certs.py | 12 ++++++++++++ + 2 files changed, 25 insertions(+), 6 deletions(-) + +diff --git a/cloudinit/config/cc_ca_certs.py b/cloudinit/config/cc_ca_certs.py +index 51b8577c..4dc08681 100644 +--- a/cloudinit/config/cc_ca_certs.py ++++ b/cloudinit/config/cc_ca_certs.py +@@ -177,14 +177,20 @@ def disable_system_ca_certs(distro_cfg): + + @param distro_cfg: A hash providing _distro_ca_certs_configs function. + """ +- if distro_cfg["ca_cert_config"] is None: ++ ++ ca_cert_cfg_fn = distro_cfg["ca_cert_config"] ++ ++ if not ca_cert_cfg_fn or not os.path.exists(ca_cert_cfg_fn): + return ++ + header_comment = ( + "# Modified by cloud-init to deselect certs due to user-data" + ) ++ + added_header = False +- if os.stat(distro_cfg["ca_cert_config"]).st_size != 0: +- orig = util.load_file(distro_cfg["ca_cert_config"]) ++ ++ if os.stat(ca_cert_cfg_fn).st_size: ++ orig = util.load_file(ca_cert_cfg_fn) + out_lines = [] + for line in orig.splitlines(): + if line == header_comment: +@@ -197,9 +203,10 @@ def disable_system_ca_certs(distro_cfg): + out_lines.append(header_comment) + added_header = True + out_lines.append("!" + line) +- util.write_file( +- distro_cfg["ca_cert_config"], "\n".join(out_lines) + "\n", omode="wb" +- ) ++ ++ util.write_file( ++ ca_cert_cfg_fn, "\n".join(out_lines) + "\n", omode="wb" ++ ) + + + def remove_default_ca_certs(distro_cfg): +diff --git a/tests/unittests/config/test_cc_ca_certs.py b/tests/unittests/config/test_cc_ca_certs.py +index 6db17485..5f1894e7 100644 +--- a/tests/unittests/config/test_cc_ca_certs.py ++++ b/tests/unittests/config/test_cc_ca_certs.py +@@ -365,6 +365,18 @@ class TestRemoveDefaultCaCerts(TestCase): + else: + assert mock_subp.call_count == 0 + ++ def test_non_existent_cert_cfg(self): ++ self.m_stat.return_value.st_size = 0 ++ ++ for distro_name in cc_ca_certs.distros: ++ conf = cc_ca_certs._distro_ca_certs_configs(distro_name) ++ with ExitStack() as mocks: ++ mocks.enter_context( ++ mock.patch.object(util, "delete_dir_contents") ++ ) ++ mocks.enter_context(mock.patch.object(subp, "subp")) ++ cc_ca_certs.disable_default_ca_certs(distro_name, conf) ++ + + class TestCACertsSchema: + """Directly test schema rather than through handle.""" diff --git a/SOURCES/0028-logging-keep-current-file-mode-of-log-file-if-its-st.patch b/SOURCES/0028-logging-keep-current-file-mode-of-log-file-if-its-st.patch new file mode 100644 index 0000000..9de8369 --- /dev/null +++ b/SOURCES/0028-logging-keep-current-file-mode-of-log-file-if-its-st.patch @@ -0,0 +1,172 @@ +From 1cecfe4bc3d7e4806d1890615a119e478decd5fd Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Thu, 20 Jul 2023 23:56:01 +0530 +Subject: [PATCH] logging: keep current file mode of log file if its stricter + than the new mode (#4250) + +By default, the cloud init log file is created with mode 0o644 with +`preserve_mode` parameter of `write_file()` set to False. This means that when +an existing log file is found, its mode will be unconditionally reset to the +mode 0o644. It is possible that this might cause the change of the mode of the +log file from the current more stricter mode to a less strict mode +(when the new mode 0o644 is less strict than the existing mode of the file). + +In order to mitigate the above issue, check the current mode of the log file +and if the current mode is stricter than the default new mode 0o644, then +preserve the current mode of the file. + +Fixes GH-4243 + +Signed-off-by: Ani Sinha +(cherry picked from commit a0e4ec15a1adffabd1c539879514eae4807c834c) + + Conflicts: + tests/unittests/test_util.py +--- + cloudinit/stages.py | 15 ++++++++++++++- + cloudinit/util.py | 23 +++++++++++++++++++++++ + tests/unittests/test_stages.py | 23 ++++++++++++++++------- + tests/unittests/test_util.py | 24 ++++++++++++++++++++++++ + 4 files changed, 77 insertions(+), 8 deletions(-) + +diff --git a/cloudinit/stages.py b/cloudinit/stages.py +index 21f30a1f..979179af 100644 +--- a/cloudinit/stages.py ++++ b/cloudinit/stages.py +@@ -200,12 +200,25 @@ class Init: + self._initialize_filesystem() + + def _initialize_filesystem(self): ++ mode = 0o640 ++ fmode = None ++ + util.ensure_dirs(self._initial_subdirs()) + log_file = util.get_cfg_option_str(self.cfg, "def_log_file") + if log_file: + # At this point the log file should have already been created + # in the setupLogging function of log.py +- util.ensure_file(log_file, mode=0o640, preserve_mode=False) ++ ++ try: ++ fmode = util.get_permissions(log_file) ++ except OSError: ++ pass ++ ++ # if existing file mode fmode is stricter, do not change it. ++ if fmode and util.compare_permission(fmode, mode) < 0: ++ mode = fmode ++ ++ util.ensure_file(log_file, mode, preserve_mode=False) + perms = self.cfg.get("syslog_fix_perms") + if not perms: + perms = {} +diff --git a/cloudinit/util.py b/cloudinit/util.py +index 4a8e3d3b..af617e73 100644 +--- a/cloudinit/util.py ++++ b/cloudinit/util.py +@@ -2099,6 +2099,29 @@ def safe_int(possible_int): + return None + + ++def compare_permission(mode1, mode2): ++ """Compare two file modes in octal. ++ ++ If mode1 is less restrictive than mode2 return 1 ++ If mode1 is more restrictive than mode2 return -1 ++ If mode1 is same as mode2, return 0 ++ ++ The comparison starts from the permission of the ++ set of users in "others" and then works up to the ++ permission of "user" set. ++ """ ++ # Convert modes to octal and reverse the last 3 digits ++ # so 0o640 would be become 0o046 ++ mode1_oct = oct(mode1)[2:].rjust(3, "0") ++ mode2_oct = oct(mode2)[2:].rjust(3, "0") ++ m1 = int(mode1_oct[:-3] + mode1_oct[-3:][::-1], 8) ++ m2 = int(mode2_oct[:-3] + mode2_oct[-3:][::-1], 8) ++ ++ # Then do a traditional cmp() ++ # https://docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons ++ return (m1 > m2) - (m1 < m2) ++ ++ + def chmod(path, mode): + real_mode = safe_int(mode) + if path and real_mode: +diff --git a/tests/unittests/test_stages.py b/tests/unittests/test_stages.py +index a61f9df9..831ea9f2 100644 +--- a/tests/unittests/test_stages.py ++++ b/tests/unittests/test_stages.py +@@ -606,13 +606,22 @@ class TestInit_InitializeFilesystem: + # Assert we create it 0o640 by default if it doesn't already exist + assert 0o640 == stat.S_IMODE(log_file.stat().mode) + +- def test_existing_file_permissions(self, init, tmpdir): ++ @pytest.mark.parametrize( ++ "set_perms,expected_perms", ++ [ ++ (0o640, 0o640), ++ (0o606, 0o640), ++ (0o600, 0o600), ++ ], ++ ) ++ def test_existing_file_permissions( ++ self, init, tmpdir, set_perms, expected_perms ++ ): + """Test file permissions are set as expected. + +- CIS Hardening requires 640 permissions. These permissions are +- currently hardcoded on every boot, but if there's ever a reason +- to change this, we need to then ensure that they +- are *not* set every boot. ++ CIS Hardening requires 640 permissions. If the file has looser ++ permissions, then hard code 640. If the file has tighter ++ permissions, then leave them as they are + + See https://bugs.launchpad.net/cloud-init/+bug/1900837. + """ +@@ -620,9 +629,9 @@ class TestInit_InitializeFilesystem: + log_file.ensure() + # Use a mode that will never be made the default so this test will + # always be valid +- log_file.chmod(0o606) ++ log_file.chmod(set_perms) + init._cfg = {"def_log_file": str(log_file)} + + init._initialize_filesystem() + +- assert 0o640 == stat.S_IMODE(log_file.stat().mode) ++ assert expected_perms == stat.S_IMODE(log_file.stat().mode) +diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py +index 17182d06..289a4234 100644 +--- a/tests/unittests/test_util.py ++++ b/tests/unittests/test_util.py +@@ -3051,3 +3051,27 @@ class TestVersion: + ) + def test_from_str(self, str_ver, cls_ver): + assert util.Version.from_str(str_ver) == cls_ver ++ ++ ++class TestComparePermissions: ++ @pytest.mark.parametrize( ++ "perm1,perm2,expected", ++ [ ++ (0o777, 0o777, 0), ++ (0o000, 0o000, 0), ++ (0o421, 0o421, 0), ++ (0o1640, 0o1640, 0), ++ (0o1407, 0o1600, 1), ++ (0o1600, 0o1407, -1), ++ (0o407, 0o600, 1), ++ (0o600, 0o407, -1), ++ (0o007, 0o700, 1), ++ (0o700, 0o007, -1), ++ (0o077, 0o100, 1), ++ (0o644, 0o640, 1), ++ (0o640, 0o600, 1), ++ (0o600, 0o400, 1), ++ ], ++ ) ++ def test_compare_permissions(self, perm1, perm2, expected): ++ assert util.compare_permission(perm1, perm2) == expected diff --git a/SOURCES/0029-DS-VMware-modify-a-few-log-level-4284.patch b/SOURCES/0029-DS-VMware-modify-a-few-log-level-4284.patch new file mode 100644 index 0000000..f8d2e74 --- /dev/null +++ b/SOURCES/0029-DS-VMware-modify-a-few-log-level-4284.patch @@ -0,0 +1,62 @@ +From 25ac8bb44af554a040f0dfa9b52e9241a33a4845 Mon Sep 17 00:00:00 2001 +From: PengpengSun <40026211+PengpengSun@users.noreply.github.com> +Date: Tue, 25 Jul 2023 05:21:46 +0800 +Subject: [PATCH] DS VMware: modify a few log level (#4284) + +Multiple ip addresses are common scenario for modern Linux, so set +debug log level for such cases. + +(cherry picked from commit 4a6a9d3f6c8fe213c51f6c1336f1dd378bf4bdca) +Signed-off-by: Ani Sinha +--- + cloudinit/sources/DataSourceVMware.py | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/cloudinit/sources/DataSourceVMware.py b/cloudinit/sources/DataSourceVMware.py +index 07a80222..bc3b5a5f 100644 +--- a/cloudinit/sources/DataSourceVMware.py ++++ b/cloudinit/sources/DataSourceVMware.py +@@ -1,6 +1,6 @@ + # Cloud-Init DataSource for VMware + # +-# Copyright (c) 2018-2022 VMware, Inc. All Rights Reserved. ++# Copyright (c) 2018-2023 VMware, Inc. All Rights Reserved. + # + # Authors: Anish Swaminathan + # Andrew Kutz +@@ -719,7 +719,7 @@ def get_default_ip_addrs(): + af_inet4 = addr4_fams.get(netifaces.AF_INET) + if af_inet4: + if len(af_inet4) > 1: +- LOG.warning( ++ LOG.debug( + "device %s has more than one ipv4 address: %s", + dev4, + af_inet4, +@@ -737,7 +737,7 @@ def get_default_ip_addrs(): + af_inet6 = addr6_fams.get(netifaces.AF_INET6) + if af_inet6: + if len(af_inet6) > 1: +- LOG.warning( ++ LOG.debug( + "device %s has more than one ipv6 address: %s", + dev6, + af_inet6, +@@ -752,7 +752,7 @@ def get_default_ip_addrs(): + af_inet6 = addr4_fams.get(netifaces.AF_INET6) + if af_inet6: + if len(af_inet6) > 1: +- LOG.warning( ++ LOG.debug( + "device %s has more than one ipv6 address: %s", + dev4, + af_inet6, +@@ -767,7 +767,7 @@ def get_default_ip_addrs(): + af_inet4 = addr6_fams.get(netifaces.AF_INET) + if af_inet4: + if len(af_inet4) > 1: +- LOG.warning( ++ LOG.debug( + "device %s has more than one ipv4 address: %s", + dev6, + af_inet4, diff --git a/SOURCES/0030-NM-renderer-set-default-IPv6-addr-gen-mode-for-all-i.patch b/SOURCES/0030-NM-renderer-set-default-IPv6-addr-gen-mode-for-all-i.patch new file mode 100644 index 0000000..680622b --- /dev/null +++ b/SOURCES/0030-NM-renderer-set-default-IPv6-addr-gen-mode-for-all-i.patch @@ -0,0 +1,283 @@ +From c720ab9703752535767691a31e4720e11674bb1f Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Fri, 4 Aug 2023 08:58:26 +0530 +Subject: [PATCH] NM renderer: set default IPv6 addr-gen-mode for all + interfaces to eui64 (#4291) + +By default, NetworkManager renderer in cloud-init does not set any specific +method for IPV6 addr-gen-mode in the keyfiles it writes. Hence, implicitly the +mode is set to `eui64` in the absence of any global addr-gen-mode option in +NetworkManager configuration. +Later when other interfaces get added via D-Bus API or by using nmcli commands +without explictly setting an addr-gen-mode, NM auto generates new profiles for +those interfaces with addr-gen-mode set to `stable-privacy`. This introduces +inconsistency of configurations between interfaces based on how they were +added. This can cause problems for the customers. + +In this change, cloud-init overrides NetworkManager's preferred default of +`stable-privacy` to use EUI64 using a drop in NetworkManager configuration +file. This setting can be overriden by using global-connection-defaults +setting in /etc/NetworkManager/NetworkManager.conf file. + +RHBZ: 2188388 + +Signed-off-by: Ani Sinha +(cherry picked from commit d41264cb4297a4b143a23f3677d33b81fbfc6e8e) + +Conflicts: + tests/unittests/test_net.py +--- + cloudinit/net/network_manager.py | 21 ++++++++ + tests/unittests/test_net.py | 91 +++++++++++++++++++++++++------- + 2 files changed, 94 insertions(+), 18 deletions(-) + +diff --git a/cloudinit/net/network_manager.py b/cloudinit/net/network_manager.py +index ca216928..8047f796 100644 +--- a/cloudinit/net/network_manager.py ++++ b/cloudinit/net/network_manager.py +@@ -21,6 +21,15 @@ from cloudinit.net.network_state import NetworkState + NM_RUN_DIR = "/etc/NetworkManager" + NM_LIB_DIR = "/usr/lib/NetworkManager" + NM_CFG_FILE = "/etc/NetworkManager/NetworkManager.conf" ++NM_IPV6_ADDR_GEN_CONF = """# This is generated by cloud-init. Do not edit. ++# ++[.config] ++ enable=nm-version-min:1.40 ++[connection.30-cloud-init-ip6-addr-gen-mode] ++ # Select EUI64 to be used if the profile does not specify it. ++ ipv6.addr-gen-mode=0 ++ ++""" + LOG = logging.getLogger(__name__) + + +@@ -368,6 +377,12 @@ class Renderer(renderer.Renderer): + name = conn_filename(con_id, target) + util.write_file(name, conn.dump(), 0o600) + ++ # Select EUI64 to be used by default by NM for creating the address ++ # for use with RFC4862 IPv6 Stateless Address Autoconfiguration. ++ util.write_file( ++ cloud_init_nm_conf_filename(target), NM_IPV6_ADDR_GEN_CONF, 0o600 ++ ) ++ + + def conn_filename(con_id, target=None): + target_con_dir = subp.target_path(target, NM_RUN_DIR) +@@ -375,6 +390,12 @@ def conn_filename(con_id, target=None): + return f"{target_con_dir}/system-connections/{con_file}" + + ++def cloud_init_nm_conf_filename(target=None): ++ target_con_dir = subp.target_path(target, NM_RUN_DIR) ++ conf_file = "30-cloud-init-ip6-addr-gen-mode.conf" ++ return f"{target_con_dir}/conf.d/{conf_file}" ++ ++ + def available(target=None): + # TODO: Move `uses_systemd` to a more appropriate location + # It is imported here to avoid circular import +diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py +index fd656a57..d49da696 100644 +--- a/tests/unittests/test_net.py ++++ b/tests/unittests/test_net.py +@@ -5679,9 +5679,25 @@ class TestNetworkManagerRendering(CiTestCase): + with_logs = True + + scripts_dir = "/etc/NetworkManager/system-connections" ++ conf_dir = "/etc/NetworkManager/conf.d" + + expected_name = "expected_network_manager" + ++ expected_conf_d = { ++ "30-cloud-init-ip6-addr-gen-mode.conf": textwrap.dedent( ++ """\ ++ # This is generated by cloud-init. Do not edit. ++ # ++ [.config] ++ enable=nm-version-min:1.40 ++ [connection.30-cloud-init-ip6-addr-gen-mode] ++ # Select EUI64 to be used if the profile does not specify it. ++ ipv6.addr-gen-mode=0 ++ ++ """ ++ ), ++ } ++ + def _get_renderer(self): + return network_manager.Renderer() + +@@ -5700,11 +5716,19 @@ class TestNetworkManagerRendering(CiTestCase): + renderer.render_network_state(ns, target=dir) + return dir2dict(dir) + +- def _compare_files_to_expected(self, expected, found): ++ def _compare_files_to_expected( ++ self, expected_scripts, expected_conf, found ++ ): + orig_maxdiff = self.maxDiff +- expected_d = dict( +- (os.path.join(self.scripts_dir, k), v) for k, v in expected.items() ++ conf_d = dict( ++ (os.path.join(self.conf_dir, k), v) ++ for k, v in expected_conf.items() ++ ) ++ scripts_d = dict( ++ (os.path.join(self.scripts_dir, k), v) ++ for k, v in expected_scripts.items() + ) ++ expected_d = {**conf_d, **scripts_d} + + try: + self.maxDiff = None +@@ -5765,6 +5789,7 @@ class TestNetworkManagerRendering(CiTestCase): + """ + ), + }, ++ self.expected_conf_d, + found, + ) + +@@ -5820,8 +5845,9 @@ class TestNetworkManagerRendering(CiTestCase): + gateway=10.0.2.2 + + """ +- ), ++ ) + }, ++ self.expected_conf_d, + found, + ) + +@@ -5857,33 +5883,44 @@ class TestNetworkManagerRendering(CiTestCase): + """ + ), + }, ++ self.expected_conf_d, + found, + ) + + def test_bond_config(self): + entry = NETWORK_CONFIGS["bond"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_vlan_config(self): + entry = NETWORK_CONFIGS["vlan"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_bridge_config(self): + entry = NETWORK_CONFIGS["bridge"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_manual_config(self): + entry = NETWORK_CONFIGS["manual"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_all_config(self): + entry = NETWORK_CONFIGS["all"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + self.assertNotIn( + "WARNING: Network config: ignoring eth0.101 device-level mtu", + self.logs.getvalue(), +@@ -5892,12 +5929,16 @@ class TestNetworkManagerRendering(CiTestCase): + def test_small_config(self): + entry = NETWORK_CONFIGS["small"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_v4_and_v6_static_config(self): + entry = NETWORK_CONFIGS["v4_and_v6_static"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + expected_msg = ( + "WARNING: Network config: ignoring iface0 device-level mtu:8999" + " because ipv4 subnet-level mtu:9000 provided." +@@ -5907,41 +5948,55 @@ class TestNetworkManagerRendering(CiTestCase): + def test_dhcpv6_only_config(self): + entry = NETWORK_CONFIGS["dhcpv6_only"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_simple_render_ipv6_slaac(self): + entry = NETWORK_CONFIGS["ipv6_slaac"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_dhcpv6_stateless_config(self): + entry = NETWORK_CONFIGS["dhcpv6_stateless"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_wakeonlan_disabled_config_v2(self): + entry = NETWORK_CONFIGS["wakeonlan_disabled"] + found = self._render_and_read( + network_config=yaml.load(entry["yaml_v2"]) + ) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_wakeonlan_enabled_config_v2(self): + entry = NETWORK_CONFIGS["wakeonlan_enabled"] + found = self._render_and_read( + network_config=yaml.load(entry["yaml_v2"]) + ) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_render_v4_and_v6(self): + entry = NETWORK_CONFIGS["v4_and_v6"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_render_v6_and_v4(self): + entry = NETWORK_CONFIGS["v6_and_v4"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + + @mock.patch( diff --git a/SOURCES/ci-Align-rhel-custom-files-with-upstream-1431.patch b/SOURCES/ci-Align-rhel-custom-files-with-upstream-1431.patch deleted file mode 100644 index ec79047..0000000 --- a/SOURCES/ci-Align-rhel-custom-files-with-upstream-1431.patch +++ /dev/null @@ -1,256 +0,0 @@ -From 8e599c618ba33f7ed572f752fc9201ca44e41868 Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Wed, 18 May 2022 16:21:45 +0200 -Subject: [PATCH 4/5] Align rhel custom files with upstream (#1431) - -RH-Author: Emanuele Giuseppe Esposito -RH-MergeRequest: 26: Align rhel custom files with upstream (#1431) -RH-Commit: [1/2] edac80c4fa3a11d093ee0e7260796566a7eb141e (eesposit/cloud-init-centos-) -RH-Bugzilla: 2088448 -RH-Acked-by: Vitaly Kuznetsov -RH-Acked-by: Miroslav Rezanina - -commit 9624758f91b61f4711e8d7b5c83075b5d23e0c43 -Author: Emanuele Giuseppe Esposito -Date: Wed May 18 15:18:04 2022 +0200 - - Align rhel custom files with upstream (#1431) - - So far RHEL had its own custom .service and cloud.cfg files, - that diverged from upstream. We always replaced the generated files - with the ones we had. - - This caused only confusion and made it harder to rebase and backport - patches targeting these files. - At the same time, we are going to delete our custom downstream-only files - and use the ones generated by .tmpl. - - The mapping is: - config/cloud.cfg.tmpl -> rhel/cloud.cfg - systemd/* -> rhel/systemd/* - - Such rhel-specific files are open and available in the Centos repo: - https://gitlab.com/redhat/centos-stream/src/cloud-init - - With this commit, we are also introducing modules in cloud.cfg that - were not in the default rhel cfg file, even though they should already - have been there with previous rebases and releases. - Anyways such modules support rhel as distro, and - therefore should cause no harm. - - Signed-off-by: Emanuele Giuseppe Esposito - - RHBZ: 2082071 - -Signed-off-by: Emanuele Giuseppe Esposito ---- - config/cloud.cfg.tmpl | 23 +++++++++++++++++++++++ - systemd/cloud-config.service.tmpl | 4 ++++ - systemd/cloud-final.service.tmpl | 13 +++++++++++++ - systemd/cloud-init-local.service.tmpl | 22 +++++++++++++++++++++- - systemd/cloud-init.service.tmpl | 6 +++++- - tests/unittests/test_render_cloudcfg.py | 1 + - 6 files changed, 67 insertions(+), 2 deletions(-) - -diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl -index 86beee3c..f4d2fd14 100644 ---- a/config/cloud.cfg.tmpl -+++ b/config/cloud.cfg.tmpl -@@ -34,7 +34,11 @@ disable_root: true - - {% if variant in ["almalinux", "alpine", "amazon", "centos", "cloudlinux", "eurolinux", - "fedora", "miraclelinux", "openEuler", "rhel", "rocky", "virtuozzo"] %} -+{% if variant == "rhel" %} -+mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service,_netdev', '0', '2'] -+{% else %} - mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2'] -+{% endif %} - {% if variant == "amazon" %} - resize_rootfs: noblock - {% endif %} -@@ -66,6 +70,14 @@ network: - config: disabled - {% endif %} - -+{% if variant == "rhel" %} -+# Default redhat settings: -+ssh_deletekeys: true -+ssh_genkeytypes: ['rsa', 'ecdsa', 'ed25519'] -+syslog_fix_perms: ~ -+disable_vmware_customization: false -+{% endif %} -+ - # The modules that run in the 'init' stage - cloud_init_modules: - - migrator -@@ -107,10 +119,15 @@ cloud_config_modules: - {% endif %} - {% if variant not in ["photon"] %} - - ssh-import-id -+{% if variant not in ["rhel"] %} - - keyboard -+{% endif %} - - locale - {% endif %} - - set-passwords -+{% if variant in ["rhel"] %} -+ - rh_subscription -+{% endif %} - {% if variant in ["rhel", "fedora", "photon"] %} - {% if variant not in ["photon"] %} - - spacewalk -@@ -239,6 +256,10 @@ system_info: - name: ec2-user - lock_passwd: True - gecos: EC2 Default User -+{% elif variant == "rhel" %} -+ name: cloud-user -+ lock_passwd: true -+ gecos: Cloud User - {% else %} - name: {{ variant }} - lock_passwd: True -@@ -254,6 +275,8 @@ system_info: - groups: [adm, sudo] - {% elif variant == "arch" %} - groups: [wheel, users] -+{% elif variant == "rhel" %} -+ groups: [adm, systemd-journal] - {% else %} - groups: [wheel, adm, systemd-journal] - {% endif %} -diff --git a/systemd/cloud-config.service.tmpl b/systemd/cloud-config.service.tmpl -index 9d928ca2..d5568a6e 100644 ---- a/systemd/cloud-config.service.tmpl -+++ b/systemd/cloud-config.service.tmpl -@@ -4,6 +4,10 @@ Description=Apply the settings specified in cloud-config - After=network-online.target cloud-config.target - After=snapd.seeded.service - Wants=network-online.target cloud-config.target -+{% if variant == "rhel" %} -+ConditionPathExists=!/etc/cloud/cloud-init.disabled -+ConditionKernelCommandLine=!cloud-init=disabled -+{% endif %} - - [Service] - Type=oneshot -diff --git a/systemd/cloud-final.service.tmpl b/systemd/cloud-final.service.tmpl -index 8207b18c..85f423ac 100644 ---- a/systemd/cloud-final.service.tmpl -+++ b/systemd/cloud-final.service.tmpl -@@ -7,6 +7,10 @@ After=multi-user.target - Before=apt-daily.service - {% endif %} - Wants=network-online.target cloud-config.service -+{% if variant == "rhel" %} -+ConditionPathExists=!/etc/cloud/cloud-init.disabled -+ConditionKernelCommandLine=!cloud-init=disabled -+{% endif %} - - - [Service] -@@ -15,7 +19,16 @@ ExecStart=/usr/bin/cloud-init modules --mode=final - RemainAfterExit=yes - TimeoutSec=0 - KillMode=process -+{% if variant == "rhel" %} -+# Restart NetworkManager if it is present and running. -+ExecStartPost=/bin/sh -c 'u=NetworkManager.service; \ -+ out=$(systemctl show --property=SubState $u) || exit; \ -+ [ "$out" = "SubState=running" ] || exit 0; \ -+ systemctl reload-or-try-restart $u' -+{% else %} - TasksMax=infinity -+{% endif %} -+ - - # Output needs to appear in instance console output - StandardOutput=journal+console -diff --git a/systemd/cloud-init-local.service.tmpl b/systemd/cloud-init-local.service.tmpl -index 7166f640..a6b82650 100644 ---- a/systemd/cloud-init-local.service.tmpl -+++ b/systemd/cloud-init-local.service.tmpl -@@ -1,23 +1,43 @@ - ## template:jinja - [Unit] - Description=Initial cloud-init job (pre-networking) --{% if variant in ["ubuntu", "unknown", "debian"] %} -+{% if variant in ["ubuntu", "unknown", "debian", "rhel" ] %} - DefaultDependencies=no - {% endif %} - Wants=network-pre.target - After=hv_kvp_daemon.service - After=systemd-remount-fs.service -+{% if variant == "rhel" %} -+Requires=dbus.socket -+After=dbus.socket -+{% endif %} - Before=NetworkManager.service -+{% if variant == "rhel" %} -+Before=network.service -+{% endif %} - Before=network-pre.target - Before=shutdown.target -+{% if variant == "rhel" %} -+Before=firewalld.target -+Conflicts=shutdown.target -+{% endif %} - {% if variant in ["ubuntu", "unknown", "debian"] %} - Before=sysinit.target - Conflicts=shutdown.target - {% endif %} - RequiresMountsFor=/var/lib/cloud -+{% if variant == "rhel" %} -+ConditionPathExists=!/etc/cloud/cloud-init.disabled -+ConditionKernelCommandLine=!cloud-init=disabled -+{% endif %} - - [Service] - Type=oneshot -+{% if variant == "rhel" %} -+ExecStartPre=/bin/mkdir -p /run/cloud-init -+ExecStartPre=/sbin/restorecon /run/cloud-init -+ExecStartPre=/usr/bin/touch /run/cloud-init/enabled -+{% endif %} - ExecStart=/usr/bin/cloud-init init --local - ExecStart=/bin/touch /run/cloud-init/network-config-ready - RemainAfterExit=yes -diff --git a/systemd/cloud-init.service.tmpl b/systemd/cloud-init.service.tmpl -index e71e5679..c170aef7 100644 ---- a/systemd/cloud-init.service.tmpl -+++ b/systemd/cloud-init.service.tmpl -@@ -1,7 +1,7 @@ - ## template:jinja - [Unit] - Description=Initial cloud-init job (metadata service crawler) --{% if variant not in ["photon"] %} -+{% if variant not in ["photon", "rhel"] %} - DefaultDependencies=no - {% endif %} - Wants=cloud-init-local.service -@@ -36,6 +36,10 @@ Before=shutdown.target - Conflicts=shutdown.target - {% endif %} - Before=systemd-user-sessions.service -+{% if variant == "rhel" %} -+ConditionPathExists=!/etc/cloud/cloud-init.disabled -+ConditionKernelCommandLine=!cloud-init=disabled -+{% endif %} - - [Service] - Type=oneshot -diff --git a/tests/unittests/test_render_cloudcfg.py b/tests/unittests/test_render_cloudcfg.py -index 30fbd1a4..9f95d448 100644 ---- a/tests/unittests/test_render_cloudcfg.py -+++ b/tests/unittests/test_render_cloudcfg.py -@@ -68,6 +68,7 @@ class TestRenderCloudCfg: - default_user_exceptions = { - "amazon": "ec2-user", - "debian": "ubuntu", -+ "rhel": "cloud-user", - "unknown": "ubuntu", - } - default_user = system_cfg["system_info"]["default_user"]["name"] --- -2.31.1 - diff --git a/SOURCES/ci-Allow-growpart-to-resize-encrypted-partitions-1316.patch b/SOURCES/ci-Allow-growpart-to-resize-encrypted-partitions-1316.patch deleted file mode 100644 index 93d922f..0000000 --- a/SOURCES/ci-Allow-growpart-to-resize-encrypted-partitions-1316.patch +++ /dev/null @@ -1,516 +0,0 @@ -From 1176a788c23697099093b4d8a9a21f10f71ebb12 Mon Sep 17 00:00:00 2001 -From: Vitaly Kuznetsov -Date: Wed, 1 Feb 2023 10:47:07 +0100 -Subject: [PATCH] Allow growpart to resize encrypted partitions (#1316) - -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2166245 - -commit d95a331d1035d52443c470e0c00765a2c2b271cc -Author: James Falcon -Date: Tue Apr 26 19:03:13 2022 -0500 - - Allow growpart to resize encrypted partitions (#1316) - - Adds the ability for growpart to resize a LUKS formatted partition. - This involves resizing the underlying partition as well as the - filesystem. 'cryptsetup' is used for resizing. - - This relies on a file present at /cc_growpart_keydata containing - json formatted 'key' and 'slot' keys, with the key being - base64 encoded. After resize, cloud-init will destroy - the luks slot used for resizing and remove the key file. - -Conflicts: - cloudinit/config/cc_growpart.py (includes only) - -Signed-off-by: Vitaly Kuznetsov ---- - cloudinit/config/cc_growpart.py | 171 +++++++++++++++- - test-requirements.txt | 1 + - tests/unittests/config/test_cc_growpart.py | 228 +++++++++++++++++++++ - tox.ini | 1 + - 4 files changed, 400 insertions(+), 1 deletion(-) - -diff --git a/cloudinit/config/cc_growpart.py b/cloudinit/config/cc_growpart.py -index 43334caa..bdf17aba 100644 ---- a/cloudinit/config/cc_growpart.py -+++ b/cloudinit/config/cc_growpart.py -@@ -64,10 +64,16 @@ growpart is:: - ignore_growroot_disabled: - """ - -+import base64 -+import copy -+import json - import os - import os.path - import re - import stat -+from contextlib import suppress -+from pathlib import Path -+from typing import Tuple - - from cloudinit import log as logging - from cloudinit import subp, temp_utils, util -@@ -81,6 +87,8 @@ DEFAULT_CONFIG = { - "ignore_growroot_disabled": False, - } - -+KEYDATA_PATH = Path("/cc_growpart_keydata") -+ - - class RESIZE(object): - SKIPPED = "SKIPPED" -@@ -289,10 +297,128 @@ def devent2dev(devent): - return dev - - -+def get_mapped_device(blockdev): -+ """Returns underlying block device for a mapped device. -+ -+ If it is mapped, blockdev will usually take the form of -+ /dev/mapper/some_name -+ -+ If blockdev is a symlink pointing to a /dev/dm-* device, return -+ the device pointed to. Otherwise, return None. -+ """ -+ realpath = os.path.realpath(blockdev) -+ if realpath.startswith("/dev/dm-"): -+ LOG.debug("%s is a mapped device pointing to %s", blockdev, realpath) -+ return realpath -+ return None -+ -+ -+def is_encrypted(blockdev, partition) -> bool: -+ """ -+ Check if a device is an encrypted device. blockdev should have -+ a /dev/dm-* path whereas partition is something like /dev/sda1. -+ """ -+ if not subp.which("cryptsetup"): -+ LOG.debug("cryptsetup not found. Assuming no encrypted partitions") -+ return False -+ try: -+ subp.subp(["cryptsetup", "status", blockdev]) -+ except subp.ProcessExecutionError as e: -+ if e.exit_code == 4: -+ LOG.debug("Determined that %s is not encrypted", blockdev) -+ else: -+ LOG.warning( -+ "Received unexpected exit code %s from " -+ "cryptsetup status. Assuming no encrypted partitions.", -+ e.exit_code, -+ ) -+ return False -+ with suppress(subp.ProcessExecutionError): -+ subp.subp(["cryptsetup", "isLuks", partition]) -+ LOG.debug("Determined that %s is encrypted", blockdev) -+ return True -+ return False -+ -+ -+def get_underlying_partition(blockdev): -+ command = ["dmsetup", "deps", "--options=devname", blockdev] -+ dep: str = subp.subp(command)[0] # type: ignore -+ # Returned result should look something like: -+ # 1 dependencies : (vdb1) -+ if not dep.startswith("1 depend"): -+ raise RuntimeError( -+ f"Expecting '1 dependencies' from 'dmsetup'. Received: {dep}" -+ ) -+ try: -+ return f'/dev/{dep.split(": (")[1].split(")")[0]}' -+ except IndexError as e: -+ raise RuntimeError( -+ f"Ran `{command}`, but received unexpected stdout: `{dep}`" -+ ) from e -+ -+ -+def resize_encrypted(blockdev, partition) -> Tuple[str, str]: -+ """Use 'cryptsetup resize' to resize LUKS volume. -+ -+ The loaded keyfile is json formatted with 'key' and 'slot' keys. -+ key is base64 encoded. Example: -+ {"key":"XFmCwX2FHIQp0LBWaLEMiHIyfxt1SGm16VvUAVledlY=","slot":5} -+ """ -+ if not KEYDATA_PATH.exists(): -+ return (RESIZE.SKIPPED, "No encryption keyfile found") -+ try: -+ with KEYDATA_PATH.open() as f: -+ keydata = json.load(f) -+ key = keydata["key"] -+ decoded_key = base64.b64decode(key) -+ slot = keydata["slot"] -+ except Exception as e: -+ raise RuntimeError( -+ "Could not load encryption key. This is expected if " -+ "the volume has been previously resized." -+ ) from e -+ -+ try: -+ subp.subp( -+ ["cryptsetup", "--key-file", "-", "resize", blockdev], -+ data=decoded_key, -+ ) -+ finally: -+ try: -+ subp.subp( -+ [ -+ "cryptsetup", -+ "luksKillSlot", -+ "--batch-mode", -+ partition, -+ str(slot), -+ ] -+ ) -+ except subp.ProcessExecutionError as e: -+ LOG.warning( -+ "Failed to kill luks slot after resizing encrypted volume: %s", -+ e, -+ ) -+ try: -+ KEYDATA_PATH.unlink() -+ except Exception: -+ util.logexc( -+ LOG, "Failed to remove keyfile after resizing encrypted volume" -+ ) -+ -+ return ( -+ RESIZE.CHANGED, -+ f"Successfully resized encrypted volume '{blockdev}'", -+ ) -+ -+ - def resize_devices(resizer, devices): - # returns a tuple of tuples containing (entry-in-devices, action, message) -+ devices = copy.copy(devices) - info = [] -- for devent in devices: -+ -+ while devices: -+ devent = devices.pop(0) - try: - blockdev = devent2dev(devent) - except ValueError as e: -@@ -329,6 +455,49 @@ def resize_devices(resizer, devices): - ) - continue - -+ underlying_blockdev = get_mapped_device(blockdev) -+ if underlying_blockdev: -+ try: -+ # We need to resize the underlying partition first -+ partition = get_underlying_partition(blockdev) -+ if is_encrypted(underlying_blockdev, partition): -+ if partition not in [x[0] for x in info]: -+ # We shouldn't attempt to resize this mapped partition -+ # until the underlying partition is resized, so re-add -+ # our device to the beginning of the list we're -+ # iterating over, then add our underlying partition -+ # so it can get processed first -+ devices.insert(0, devent) -+ devices.insert(0, partition) -+ continue -+ status, message = resize_encrypted(blockdev, partition) -+ info.append( -+ ( -+ devent, -+ status, -+ message, -+ ) -+ ) -+ else: -+ info.append( -+ ( -+ devent, -+ RESIZE.SKIPPED, -+ f"Resizing mapped device ({blockdev}) skipped " -+ "as it is not encrypted.", -+ ) -+ ) -+ except Exception as e: -+ info.append( -+ ( -+ devent, -+ RESIZE.FAILED, -+ f"Resizing encrypted device ({blockdev}) failed: {e}", -+ ) -+ ) -+ # At this point, we WON'T resize a non-encrypted mapped device -+ # though we should probably grow the ability to -+ continue - try: - (disk, ptnum) = device_part_info(blockdev) - except (TypeError, ValueError) as e: -diff --git a/test-requirements.txt b/test-requirements.txt -index 06dfbbec..7160416a 100644 ---- a/test-requirements.txt -+++ b/test-requirements.txt -@@ -2,6 +2,7 @@ - httpretty>=0.7.1 - pytest - pytest-cov -+pytest-mock - - # Only really needed on older versions of python - setuptools -diff --git a/tests/unittests/config/test_cc_growpart.py b/tests/unittests/config/test_cc_growpart.py -index ba66f136..7d4e2629 100644 ---- a/tests/unittests/config/test_cc_growpart.py -+++ b/tests/unittests/config/test_cc_growpart.py -@@ -8,6 +8,7 @@ import shutil - import stat - import unittest - from contextlib import ExitStack -+from itertools import chain - from unittest import mock - - from cloudinit import cloud, subp, temp_utils -@@ -342,6 +343,233 @@ class TestResize(unittest.TestCase): - os.stat = real_stat - - -+class TestEncrypted: -+ """Attempt end-to-end scenarios using encrypted devices. -+ -+ Things are mocked such that: -+ - "/fake_encrypted" is mounted onto "/dev/mapper/fake" -+ - "/dev/mapper/fake" is a LUKS device and symlinked to /dev/dm-1 -+ - The partition backing "/dev/mapper/fake" is "/dev/vdx1" -+ - "/" is not encrypted and mounted onto "/dev/vdz1" -+ -+ Note that we don't (yet) support non-encrypted mapped drives, such -+ as LVM volumes. If our mount point is /dev/mapper/*, then we will -+ not resize it if it is not encrypted. -+ """ -+ -+ def _subp_side_effect(self, value, good=True, **kwargs): -+ if value[0] == "dmsetup": -+ return ("1 dependencies : (vdx1)",) -+ return mock.Mock() -+ -+ def _device_part_info_side_effect(self, value): -+ if value.startswith("/dev/mapper/"): -+ raise TypeError(f"{value} not a partition") -+ return (1024, 1024) -+ -+ def _devent2dev_side_effect(self, value): -+ if value == "/fake_encrypted": -+ return "/dev/mapper/fake" -+ elif value == "/": -+ return "/dev/vdz" -+ elif value.startswith("/dev"): -+ return value -+ raise Exception(f"unexpected value {value}") -+ -+ def _realpath_side_effect(self, value): -+ return "/dev/dm-1" if value.startswith("/dev/mapper") else value -+ -+ def assert_resize_and_cleanup(self): -+ all_subp_args = list( -+ chain(*[args[0][0] for args in self.m_subp.call_args_list]) -+ ) -+ assert "resize" in all_subp_args -+ assert "luksKillSlot" in all_subp_args -+ self.m_unlink.assert_called_once() -+ -+ def assert_no_resize_or_cleanup(self): -+ all_subp_args = list( -+ chain(*[args[0][0] for args in self.m_subp.call_args_list]) -+ ) -+ assert "resize" not in all_subp_args -+ assert "luksKillSlot" not in all_subp_args -+ self.m_unlink.assert_not_called() -+ -+ @pytest.fixture -+ def common_mocks(self, mocker): -+ # These are all "happy path" mocks which will get overridden -+ # when needed -+ mocker.patch( -+ "cloudinit.config.cc_growpart.device_part_info", -+ side_effect=self._device_part_info_side_effect, -+ ) -+ mocker.patch("os.stat") -+ mocker.patch("stat.S_ISBLK") -+ mocker.patch("stat.S_ISCHR") -+ mocker.patch( -+ "cloudinit.config.cc_growpart.devent2dev", -+ side_effect=self._devent2dev_side_effect, -+ ) -+ mocker.patch( -+ "os.path.realpath", side_effect=self._realpath_side_effect -+ ) -+ # Only place subp.which is used in cc_growpart is for cryptsetup -+ mocker.patch( -+ "cloudinit.config.cc_growpart.subp.which", -+ return_value="/usr/sbin/cryptsetup", -+ ) -+ self.m_subp = mocker.patch( -+ "cloudinit.config.cc_growpart.subp.subp", -+ side_effect=self._subp_side_effect, -+ ) -+ mocker.patch( -+ "pathlib.Path.open", -+ new_callable=mock.mock_open, -+ read_data=( -+ '{"key":"XFmCwX2FHIQp0LBWaLEMiHIyfxt1SGm16VvUAVledlY=",' -+ '"slot":5}' -+ ), -+ ) -+ mocker.patch("pathlib.Path.exists", return_value=True) -+ self.m_unlink = mocker.patch("pathlib.Path.unlink", autospec=True) -+ -+ self.resizer = mock.Mock() -+ self.resizer.resize = mock.Mock(return_value=(1024, 1024)) -+ -+ def test_resize_when_encrypted(self, common_mocks, caplog): -+ info = cc_growpart.resize_devices(self.resizer, ["/fake_encrypted"]) -+ assert len(info) == 2 -+ assert info[0][0] == "/dev/vdx1" -+ assert info[0][2].startswith("no change necessary") -+ assert info[1][0] == "/fake_encrypted" -+ assert ( -+ info[1][2] -+ == "Successfully resized encrypted volume '/dev/mapper/fake'" -+ ) -+ assert ( -+ "/dev/mapper/fake is a mapped device pointing to /dev/dm-1" -+ in caplog.text -+ ) -+ assert "Determined that /dev/dm-1 is encrypted" in caplog.text -+ -+ self.assert_resize_and_cleanup() -+ -+ def test_resize_when_unencrypted(self, common_mocks): -+ info = cc_growpart.resize_devices(self.resizer, ["/"]) -+ assert len(info) == 1 -+ assert info[0][0] == "/" -+ assert "encrypted" not in info[0][2] -+ self.assert_no_resize_or_cleanup() -+ -+ def test_encrypted_but_cryptsetup_not_found( -+ self, common_mocks, mocker, caplog -+ ): -+ mocker.patch( -+ "cloudinit.config.cc_growpart.subp.which", -+ return_value=None, -+ ) -+ info = cc_growpart.resize_devices(self.resizer, ["/fake_encrypted"]) -+ -+ assert len(info) == 1 -+ assert "skipped as it is not encrypted" in info[0][2] -+ assert "cryptsetup not found" in caplog.text -+ self.assert_no_resize_or_cleanup() -+ -+ def test_dmsetup_not_found(self, common_mocks, mocker, caplog): -+ def _subp_side_effect(value, **kwargs): -+ if value[0] == "dmsetup": -+ raise subp.ProcessExecutionError() -+ -+ mocker.patch( -+ "cloudinit.config.cc_growpart.subp.subp", -+ side_effect=_subp_side_effect, -+ ) -+ info = cc_growpart.resize_devices(self.resizer, ["/fake_encrypted"]) -+ assert len(info) == 1 -+ assert info[0][0] == "/fake_encrypted" -+ assert info[0][1] == "FAILED" -+ assert ( -+ "Resizing encrypted device (/dev/mapper/fake) failed" in info[0][2] -+ ) -+ self.assert_no_resize_or_cleanup() -+ -+ def test_unparsable_dmsetup(self, common_mocks, mocker, caplog): -+ def _subp_side_effect(value, **kwargs): -+ if value[0] == "dmsetup": -+ return ("2 dependencies",) -+ return mock.Mock() -+ -+ mocker.patch( -+ "cloudinit.config.cc_growpart.subp.subp", -+ side_effect=_subp_side_effect, -+ ) -+ info = cc_growpart.resize_devices(self.resizer, ["/fake_encrypted"]) -+ assert len(info) == 1 -+ assert info[0][0] == "/fake_encrypted" -+ assert info[0][1] == "FAILED" -+ assert ( -+ "Resizing encrypted device (/dev/mapper/fake) failed" in info[0][2] -+ ) -+ self.assert_no_resize_or_cleanup() -+ -+ def test_missing_keydata(self, common_mocks, mocker, caplog): -+ # Note that this will be standard behavior after first boot -+ # on a system with an encrypted root partition -+ mocker.patch("pathlib.Path.open", side_effect=FileNotFoundError()) -+ info = cc_growpart.resize_devices(self.resizer, ["/fake_encrypted"]) -+ assert len(info) == 2 -+ assert info[0][0] == "/dev/vdx1" -+ assert info[0][2].startswith("no change necessary") -+ assert info[1][0] == "/fake_encrypted" -+ assert info[1][1] == "FAILED" -+ assert ( -+ info[1][2] -+ == "Resizing encrypted device (/dev/mapper/fake) failed: Could " -+ "not load encryption key. This is expected if the volume has " -+ "been previously resized." -+ ) -+ self.assert_no_resize_or_cleanup() -+ -+ def test_resize_failed(self, common_mocks, mocker, caplog): -+ def _subp_side_effect(value, **kwargs): -+ if value[0] == "dmsetup": -+ return ("1 dependencies : (vdx1)",) -+ elif value[0] == "cryptsetup" and "resize" in value: -+ raise subp.ProcessExecutionError() -+ return mock.Mock() -+ -+ self.m_subp = mocker.patch( -+ "cloudinit.config.cc_growpart.subp.subp", -+ side_effect=_subp_side_effect, -+ ) -+ -+ info = cc_growpart.resize_devices(self.resizer, ["/fake_encrypted"]) -+ assert len(info) == 2 -+ assert info[0][0] == "/dev/vdx1" -+ assert info[0][2].startswith("no change necessary") -+ assert info[1][0] == "/fake_encrypted" -+ assert info[1][1] == "FAILED" -+ assert ( -+ "Resizing encrypted device (/dev/mapper/fake) failed" in info[1][2] -+ ) -+ # Assert we still cleanup -+ all_subp_args = list( -+ chain(*[args[0][0] for args in self.m_subp.call_args_list]) -+ ) -+ assert "luksKillSlot" in all_subp_args -+ self.m_unlink.assert_called_once() -+ -+ def test_resize_skipped(self, common_mocks, mocker, caplog): -+ mocker.patch("pathlib.Path.exists", return_value=False) -+ info = cc_growpart.resize_devices(self.resizer, ["/fake_encrypted"]) -+ assert len(info) == 2 -+ assert info[1] == ( -+ "/fake_encrypted", -+ "SKIPPED", -+ "No encryption keyfile found", -+ ) -+ -+ - def simple_device_part_info(devpath): - # simple stupid return (/dev/vda, 1) for /dev/vda - ret = re.search("([^0-9]*)([0-9]*)$", devpath) -diff --git a/tox.ini b/tox.ini -index c494cb94..04a206f2 100644 ---- a/tox.ini -+++ b/tox.ini -@@ -108,6 +108,7 @@ deps = - # test-requirements - pytest==3.3.2 - pytest-cov==2.5.1 -+ pytest-mock==1.7.1 - # Needed by pytest and default causes failures - attrs==17.4.0 - --- -2.39.1 - diff --git a/SOURCES/ci-Ensure-network-ready-before-cloud-init-service-runs-.patch b/SOURCES/ci-Ensure-network-ready-before-cloud-init-service-runs-.patch deleted file mode 100644 index cd93ee6..0000000 --- a/SOURCES/ci-Ensure-network-ready-before-cloud-init-service-runs-.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 14d1952c17637b80923d1bfaf3b6b5f8cf032147 Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Wed, 14 Dec 2022 09:31:51 +0100 -Subject: [PATCH] Ensure network ready before cloud-init service runs on RHEL - (#1893) - -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2152100 - -commit 6e725f36647407d201af0603d7db11fc96a93d4d -Author: James Falcon -Date: Tue Dec 13 10:55:23 2022 -0600 - - Ensure network ready before cloud-init service runs on RHEL (#1893) - - LP: #1998655 - -Signed-off-by: Emanuele Giuseppe Esposito ---- - systemd/cloud-init.service.tmpl | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/systemd/cloud-init.service.tmpl b/systemd/cloud-init.service.tmpl -index c170aef7..fc984d5c 100644 ---- a/systemd/cloud-init.service.tmpl -+++ b/systemd/cloud-init.service.tmpl -@@ -16,6 +16,7 @@ After=networking.service - "miraclelinux", "openEuler", "rhel", "rocky", "virtuozzo"] %} - After=network.service - After=NetworkManager.service -+After=NetworkManager-wait-online.service - {% endif %} - {% if variant in ["suse"] %} - After=wicked.service --- -2.38.1 - diff --git a/SOURCES/ci-Honor-system-locale-for-RHEL-1355.patch b/SOURCES/ci-Honor-system-locale-for-RHEL-1355.patch deleted file mode 100644 index c362160..0000000 --- a/SOURCES/ci-Honor-system-locale-for-RHEL-1355.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 53e3f8ab9008fec8400f96918c2129f7defe6a70 Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Fri, 10 Jun 2022 20:51:55 +0200 -Subject: [PATCH 1/3] Honor system locale for RHEL (#1355) - -RH-Author: Emanuele Giuseppe Esposito -RH-MergeRequest: 29: Honor system locale for RHEL (#1355) -RH-Commit: [1/1] d571126fe6add8dc34a22c869d4e1a07a7373d8d (eesposit/cloud-init-centos-) -RH-Bugzilla: 2061604 -RH-Acked-by: Mohamed Gamal Morsy -RH-Acked-by: Vitaly Kuznetsov - -commit 58da7d856274e9ca2b507128d6f186e0e6abfe06 -Author: Wei Shi -Date: Wed Mar 30 23:55:30 2022 +0800 - - Honor system locale for RHEL (#1355) - - Make sure to use system locale as default on RHEL if locale is not - set in cloud-config. - - RHEL has a pre-installed cloud image using C.UTF-8 for system locale - just like ubuntu-minimal cloud image, without this patch, locale - module will set it to en_US.UTF-8 from ds default value during config - stage. - - Authored-by: Wei Shi - -Signed-off-by: Emanuele Giuseppe Esposito ---- - cloudinit/distros/rhel.py | 32 +++++++++++++++++++++++++ - tests/unittests/distros/test_generic.py | 10 ++++---- - tools/.github-cla-signers | 1 + - 3 files changed, 39 insertions(+), 4 deletions(-) - -diff --git a/cloudinit/distros/rhel.py b/cloudinit/distros/rhel.py -index 84744ece..320f4ba1 100644 ---- a/cloudinit/distros/rhel.py -+++ b/cloudinit/distros/rhel.py -@@ -7,6 +7,7 @@ - # Author: Joshua Harlow - # - # This file is part of cloud-init. See LICENSE file for license information. -+import os - - from cloudinit import distros, helpers - from cloudinit import log as logging -@@ -57,11 +58,25 @@ class Distro(distros.Distro): - # should only happen say once per instance...) - self._runner = helpers.Runners(paths) - self.osfamily = "redhat" -+ self.default_locale = "en_US.UTF-8" -+ self.system_locale = None - cfg["ssh_svcname"] = "sshd" - - def install_packages(self, pkglist): - self.package_command("install", pkgs=pkglist) - -+ def get_locale(self): -+ """Return the default locale if set, else use system locale""" -+ -+ # read system locale value -+ if not self.system_locale: -+ self.system_locale = self._read_system_locale() -+ -+ # Return system_locale setting if valid, else use default locale -+ return ( -+ self.system_locale if self.system_locale else self.default_locale -+ ) -+ - def apply_locale(self, locale, out_fn=None): - if self.uses_systemd(): - if not out_fn: -@@ -75,6 +90,23 @@ class Distro(distros.Distro): - } - rhel_util.update_sysconfig_file(out_fn, locale_cfg) - -+ def _read_system_locale(self, keyname="LANG"): -+ """Read system default locale setting, if present""" -+ if self.uses_systemd(): -+ locale_fn = self.systemd_locale_conf_fn -+ else: -+ locale_fn = self.locale_conf_fn -+ -+ if not locale_fn: -+ raise ValueError("Invalid path: %s" % locale_fn) -+ -+ if os.path.exists(locale_fn): -+ (_exists, contents) = rhel_util.read_sysconfig_file(locale_fn) -+ if keyname in contents: -+ return contents[keyname] -+ else: -+ return None -+ - def _write_hostname(self, hostname, filename): - # systemd will never update previous-hostname for us, so - # we need to do it ourselves -diff --git a/tests/unittests/distros/test_generic.py b/tests/unittests/distros/test_generic.py -index 93c5395c..fedc7300 100644 ---- a/tests/unittests/distros/test_generic.py -+++ b/tests/unittests/distros/test_generic.py -@@ -187,12 +187,14 @@ class TestGenericDistro(helpers.FilesystemMockingTestCase): - locale = d.get_locale() - self.assertEqual("C.UTF-8", locale) - -- def test_get_locale_rhel(self): -- """Test rhel distro returns NotImplementedError exception""" -+ @mock.patch("cloudinit.distros.rhel.Distro._read_system_locale") -+ def test_get_locale_rhel(self, m_locale): -+ """Test rhel distro returns locale set to C.UTF-8""" -+ m_locale.return_value = "C.UTF-8" - cls = distros.fetch("rhel") - d = cls("rhel", {}, None) -- with self.assertRaises(NotImplementedError): -- d.get_locale() -+ locale = d.get_locale() -+ self.assertEqual("C.UTF-8", locale) - - def test_expire_passwd_uses_chpasswd(self): - """Test ubuntu.expire_passwd uses the passwd command.""" -diff --git a/tools/.github-cla-signers b/tools/.github-cla-signers -index 9f71ea0c..9eb2ae38 100644 ---- a/tools/.github-cla-signers -+++ b/tools/.github-cla-signers -@@ -70,6 +70,7 @@ renanrodrigo - rhansen - riedel - sarahwzadara -+shi2wei3 - slingamn - slyon - smoser --- -2.35.1 - diff --git a/SOURCES/ci-Remove-rhel-specific-files.patch b/SOURCES/ci-Remove-rhel-specific-files.patch deleted file mode 100644 index efce1f5..0000000 --- a/SOURCES/ci-Remove-rhel-specific-files.patch +++ /dev/null @@ -1,370 +0,0 @@ -From 0ae221fe8f29555370520d05f6558eb75fe3cd42 Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Thu, 5 May 2022 11:31:33 +0200 -Subject: [PATCH 5/5] Remove rhel specific files - -RH-Author: Emanuele Giuseppe Esposito -RH-MergeRequest: 26: Align rhel custom files with upstream (#1431) -RH-Commit: [2/2] 0b9687ebab4f4039d5bbe05c00806ec7923e898d (eesposit/cloud-init-centos-) -RH-Bugzilla: 2088448 -RH-Acked-by: Vitaly Kuznetsov -RH-Acked-by: Miroslav Rezanina - -Remove all files in rhel/ directory and related commands that copy -and replace them with the generated ones. - -Also adjust setup.py, align it with upstream: -- by default, after rhel 8.3 ds-identify is in /usr/libexec, so no need to move it manually -- bash-completions work also in /usr/share, as upstream -- udev also works in /lib/udev - -Also remove rhel/README since it is outdated (chef is used in cloud.cfg) and cloud-init-tmpfiles.conf, -as it exists also in .distro. - -X-downstream-only: yes - -Signed-off-by: Emanuele Giuseppe Esposito ---- - rhel/README.rhel | 5 -- - rhel/cloud-init-tmpfiles.conf | 1 - - rhel/cloud.cfg | 69 --------------------------- - rhel/systemd/cloud-config.service | 18 ------- - rhel/systemd/cloud-config.target | 11 ----- - rhel/systemd/cloud-final.service | 24 ---------- - rhel/systemd/cloud-init-local.service | 31 ------------ - rhel/systemd/cloud-init.service | 26 ---------- - rhel/systemd/cloud-init.target | 7 --- - setup.py | 28 ++++++++++- - 11 files changed, 31 insertions(+), 210 deletions(-) - delete mode 100644 rhel/README.rhel - delete mode 100644 rhel/cloud-init-tmpfiles.conf - delete mode 100644 rhel/cloud.cfg - delete mode 100644 rhel/systemd/cloud-config.service - delete mode 100644 rhel/systemd/cloud-config.target - delete mode 100644 rhel/systemd/cloud-final.service - delete mode 100644 rhel/systemd/cloud-init-local.service - delete mode 100644 rhel/systemd/cloud-init.service - delete mode 100644 rhel/systemd/cloud-init.target - -diff --git a/rhel/README.rhel b/rhel/README.rhel -deleted file mode 100644 -index aa29630d..00000000 ---- a/rhel/README.rhel -+++ /dev/null -@@ -1,5 +0,0 @@ --The following cloud-init modules are currently unsupported on this OS: -- - apt_update_upgrade ('apt_update', 'apt_upgrade', 'apt_mirror', 'apt_preserve_sources_list', 'apt_old_mirror', 'apt_sources', 'debconf_selections', 'packages' options) -- - byobu ('byobu_by_default' option) -- - chef -- - grub_dpkg -diff --git a/rhel/cloud-init-tmpfiles.conf b/rhel/cloud-init-tmpfiles.conf -deleted file mode 100644 -index 0c6d2a3b..00000000 ---- a/rhel/cloud-init-tmpfiles.conf -+++ /dev/null -@@ -1 +0,0 @@ --d /run/cloud-init 0700 root root - - -diff --git a/rhel/cloud.cfg b/rhel/cloud.cfg -deleted file mode 100644 -index 75d5c84b..00000000 ---- a/rhel/cloud.cfg -+++ /dev/null -@@ -1,69 +0,0 @@ --users: -- - default -- --disable_root: 1 --ssh_pwauth: 0 -- --mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service,_netdev', '0', '2'] --resize_rootfs_tmp: /dev --ssh_deletekeys: 1 --ssh_genkeytypes: ['rsa', 'ecdsa', 'ed25519'] --syslog_fix_perms: ~ --disable_vmware_customization: false -- --cloud_init_modules: -- - disk_setup -- - migrator -- - bootcmd -- - write-files -- - growpart -- - resizefs -- - set_hostname -- - update_hostname -- - update_etc_hosts -- - rsyslog -- - users-groups -- - ssh -- --cloud_config_modules: -- - mounts -- - locale -- - set-passwords -- - rh_subscription -- - yum-add-repo -- - package-update-upgrade-install -- - timezone -- - puppet -- - chef -- - salt-minion -- - mcollective -- - disable-ec2-metadata -- - runcmd -- --cloud_final_modules: -- - rightscale_userdata -- - scripts-per-once -- - scripts-per-boot -- - scripts-per-instance -- - scripts-user -- - ssh-authkey-fingerprints -- - keys-to-console -- - phone-home -- - final-message -- - power-state-change -- --system_info: -- default_user: -- name: cloud-user -- lock_passwd: true -- gecos: Cloud User -- groups: [adm, systemd-journal] -- sudo: ["ALL=(ALL) NOPASSWD:ALL"] -- shell: /bin/bash -- distro: rhel -- paths: -- cloud_dir: /var/lib/cloud -- templates_dir: /etc/cloud/templates -- ssh_svcname: sshd -- --# vim:syntax=yaml -diff --git a/rhel/systemd/cloud-config.service b/rhel/systemd/cloud-config.service -deleted file mode 100644 -index f3dcd4be..00000000 ---- a/rhel/systemd/cloud-config.service -+++ /dev/null -@@ -1,18 +0,0 @@ --[Unit] --Description=Apply the settings specified in cloud-config --After=network-online.target cloud-config.target --Wants=network-online.target cloud-config.target --ConditionPathExists=!/etc/cloud/cloud-init.disabled --ConditionKernelCommandLine=!cloud-init=disabled -- --[Service] --Type=oneshot --ExecStart=/usr/bin/cloud-init modules --mode=config --RemainAfterExit=yes --TimeoutSec=0 -- --# Output needs to appear in instance console output --StandardOutput=journal+console -- --[Install] --WantedBy=cloud-init.target -diff --git a/rhel/systemd/cloud-config.target b/rhel/systemd/cloud-config.target -deleted file mode 100644 -index ae9b7d02..00000000 ---- a/rhel/systemd/cloud-config.target -+++ /dev/null -@@ -1,11 +0,0 @@ --# cloud-init normally emits a "cloud-config" upstart event to inform third --# parties that cloud-config is available, which does us no good when we're --# using systemd. cloud-config.target serves as this synchronization point --# instead. Services that would "start on cloud-config" with upstart can --# instead use "After=cloud-config.target" and "Wants=cloud-config.target" --# as appropriate. -- --[Unit] --Description=Cloud-config availability --Wants=cloud-init-local.service cloud-init.service --After=cloud-init-local.service cloud-init.service -diff --git a/rhel/systemd/cloud-final.service b/rhel/systemd/cloud-final.service -deleted file mode 100644 -index e281c0cf..00000000 ---- a/rhel/systemd/cloud-final.service -+++ /dev/null -@@ -1,24 +0,0 @@ --[Unit] --Description=Execute cloud user/final scripts --After=network-online.target cloud-config.service rc-local.service --Wants=network-online.target cloud-config.service --ConditionPathExists=!/etc/cloud/cloud-init.disabled --ConditionKernelCommandLine=!cloud-init=disabled -- --[Service] --Type=oneshot --ExecStart=/usr/bin/cloud-init modules --mode=final --RemainAfterExit=yes --TimeoutSec=0 --KillMode=process --# Restart NetworkManager if it is present and running. --ExecStartPost=/bin/sh -c 'u=NetworkManager.service; \ -- out=$(systemctl show --property=SubState $u) || exit; \ -- [ "$out" = "SubState=running" ] || exit 0; \ -- systemctl reload-or-try-restart $u' -- --# Output needs to appear in instance console output --StandardOutput=journal+console -- --[Install] --WantedBy=cloud-init.target -diff --git a/rhel/systemd/cloud-init-local.service b/rhel/systemd/cloud-init-local.service -deleted file mode 100644 -index 8f9f6c9f..00000000 ---- a/rhel/systemd/cloud-init-local.service -+++ /dev/null -@@ -1,31 +0,0 @@ --[Unit] --Description=Initial cloud-init job (pre-networking) --DefaultDependencies=no --Wants=network-pre.target --After=systemd-remount-fs.service --Requires=dbus.socket --After=dbus.socket --Before=NetworkManager.service network.service --Before=network-pre.target --Before=shutdown.target --Before=firewalld.target --Conflicts=shutdown.target --RequiresMountsFor=/var/lib/cloud --ConditionPathExists=!/etc/cloud/cloud-init.disabled --ConditionKernelCommandLine=!cloud-init=disabled -- --[Service] --Type=oneshot --ExecStartPre=/bin/mkdir -p /run/cloud-init --ExecStartPre=/sbin/restorecon /run/cloud-init --ExecStartPre=/usr/bin/touch /run/cloud-init/enabled --ExecStart=/usr/bin/cloud-init init --local --ExecStart=/bin/touch /run/cloud-init/network-config-ready --RemainAfterExit=yes --TimeoutSec=0 -- --# Output needs to appear in instance console output --StandardOutput=journal+console -- --[Install] --WantedBy=cloud-init.target -diff --git a/rhel/systemd/cloud-init.service b/rhel/systemd/cloud-init.service -deleted file mode 100644 -index 0b3d796d..00000000 ---- a/rhel/systemd/cloud-init.service -+++ /dev/null -@@ -1,26 +0,0 @@ --[Unit] --Description=Initial cloud-init job (metadata service crawler) --Wants=cloud-init-local.service --Wants=sshd-keygen.service --Wants=sshd.service --After=cloud-init-local.service --After=NetworkManager.service network.service --After=NetworkManager-wait-online.service --Before=network-online.target --Before=sshd-keygen.service --Before=sshd.service --Before=systemd-user-sessions.service --ConditionPathExists=!/etc/cloud/cloud-init.disabled --ConditionKernelCommandLine=!cloud-init=disabled -- --[Service] --Type=oneshot --ExecStart=/usr/bin/cloud-init init --RemainAfterExit=yes --TimeoutSec=0 -- --# Output needs to appear in instance console output --StandardOutput=journal+console -- --[Install] --WantedBy=cloud-init.target -diff --git a/rhel/systemd/cloud-init.target b/rhel/systemd/cloud-init.target -deleted file mode 100644 -index 083c3b6f..00000000 ---- a/rhel/systemd/cloud-init.target -+++ /dev/null -@@ -1,7 +0,0 @@ --# cloud-init target is enabled by cloud-init-generator --# To disable it you can either: --# a.) boot with kernel cmdline of 'cloud-init=disabled' --# b.) touch a file /etc/cloud/cloud-init.disabled --[Unit] --Description=Cloud-init target --After=multi-user.target -diff --git a/setup.py b/setup.py -index 3c377eaa..a9132d2c 100755 ---- a/setup.py -+++ b/setup.py -@@ -139,6 +139,21 @@ INITSYS_FILES = { - "sysvinit_deb": [f for f in glob("sysvinit/debian/*") if is_f(f)], - "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") -+ + glob("systemd/*.service") -+ + glob("systemd/*.socket") -+ + glob("systemd/*.target") -+ ) -+ if (is_f(f) and not is_generator(f)) -+ ], -+ "systemd.generators": [ -+ render_tmpl(f, mode=0o755) -+ for f in glob("systemd/*") -+ if is_f(f) and is_generator(f) -+ ], - "upstart": [f for f in glob("upstart/*") if is_f(f)], - } - INITSYS_ROOTS = { -@@ -148,6 +163,10 @@ INITSYS_ROOTS = { - "sysvinit_deb": "etc/init.d", - "sysvinit_openrc": "etc/init.d", - "sysvinit_suse": "etc/init.d", -+ "systemd": pkg_config_read("systemd", "systemdsystemunitdir"), -+ "systemd.generators": pkg_config_read( -+ "systemd", "systemdsystemgeneratordir" -+ ), - "upstart": "etc/init/", - } - INITSYS_TYPES = sorted([f.partition(".")[0] for f in INITSYS_ROOTS.keys()]) -@@ -262,13 +281,15 @@ data_files = [ - ( - USR_LIB_EXEC + "/cloud-init", - [ -+ "tools/ds-identify", - "tools/hook-hotplug", - "tools/uncloud-init", - "tools/write-ssh-key-fingerprints", - ], - ), - ( -- ETC + "/bash_completion.d", ["bash_completion/cloud-init"], -+ USR + "/share/bash-completion/completions", -+ ["bash_completion/cloud-init"], - ), - (USR + "/share/doc/cloud-init", [f for f in glob("doc/*") if is_f(f)]), - ( -@@ -287,7 +308,8 @@ if not platform.system().endswith("BSD"): - ETC + "/NetworkManager/dispatcher.d/", - ["tools/hook-network-manager"], - ), -- ("/usr/lib/udev/rules.d", [f for f in glob("udev/*.rules")]), -+ (ETC + "/dhcp/dhclient-exit-hooks.d/", ["tools/hook-dhclient"]), -+ (LIB + "/udev/rules.d", [f for f in glob("udev/*.rules")]), - ( - ETC + "/systemd/system/sshd-keygen@.service.d/", - ["systemd/disable-sshd-keygen-if-cloud-init-active.conf"], -@@ -317,6 +339,8 @@ setuptools.setup( - scripts=["tools/cloud-init-per"], - license="Dual-licensed under GPLv3 or Apache 2.0", - data_files=data_files, -+ install_requires=requirements, -+ cmdclass=cmdclass, - entry_points={ - "console_scripts": [ - "cloud-init = cloudinit.cmd.main:main", --- -2.31.1 - diff --git a/SOURCES/ci-Revert-Revert-Setting-highest-autoconnect-priority-f.patch b/SOURCES/ci-Revert-Revert-Setting-highest-autoconnect-priority-f.patch deleted file mode 100644 index d919da9..0000000 --- a/SOURCES/ci-Revert-Revert-Setting-highest-autoconnect-priority-f.patch +++ /dev/null @@ -1,37 +0,0 @@ -From c843f5cf7152846da3422185a6ad344dd47604e6 Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Mon, 8 Aug 2022 10:02:48 +0200 -Subject: [PATCH 3/3] Revert "Revert "Setting highest autoconnect priority for - network-scripts"" - -RH-Author: Emanuele Giuseppe Esposito -RH-MergeRequest: 31: Revert "Revert "Setting highest autoconnect priority for network-scripts"" -RH-Commit: [3/3] 09b83fb559675a2fcd4fc5394b251f034b92c1bc (eesposit/cloud-init-centos-) -RH-Bugzilla: 2107463 2104389 2117532 2098501 -RH-Acked-by: Eduardo Otubo -RH-Acked-by: Vitaly Kuznetsov -RH-Acked-by: Mohamed Gamal Morsy - -Reverting NM means we also need to restore this patch -This reverts commit 0eba5c6194017ef493a735cb24757c57d8af7b59. - -Signed-off-by: Emanuele Giuseppe Esposito ---- - cloudinit/net/sysconfig.py | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py -index d8c53312..b50035b5 100644 ---- a/cloudinit/net/sysconfig.py -+++ b/cloudinit/net/sysconfig.py -@@ -337,6 +337,7 @@ class Renderer(renderer.Renderer): - "ONBOOT": True, - "USERCTL": False, - "BOOTPROTO": "none", -+ "AUTOCONNECT_PRIORITY": 999 - }, - "suse": {"BOOTPROTO": "static", "STARTMODE": "auto"}, - } --- -2.31.1 - diff --git a/SOURCES/ci-Revert-Setting-highest-autoconnect-priority-for-netw.patch b/SOURCES/ci-Revert-Setting-highest-autoconnect-priority-for-netw.patch deleted file mode 100644 index bd183a4..0000000 --- a/SOURCES/ci-Revert-Setting-highest-autoconnect-priority-for-netw.patch +++ /dev/null @@ -1,37 +0,0 @@ -From e5e2ba9e21ac40ec7b8fe1c1dcf501eaeb9f66bf Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Mon, 2 May 2022 14:43:17 +0200 -Subject: [PATCH 3/5] Revert "Setting highest autoconnect priority for - network-scripts" - -RH-Author: Emanuele Giuseppe Esposito -RH-MergeRequest: 24: Add native NetworkManager support (#1224) -RH-Commit: [3/3] 06c87581fc42b6827ad9df600f3dd76d51ced0d0 (eesposit/cloud-init-centos-) -RH-Bugzilla: 2056964 -RH-Acked-by: Miroslav Rezanina -RH-Acked-by: Vitaly Kuznetsov - -This reverts commit 0ef0c86350aa5f800f8393a432f431e2818c8938, -since it was a temporary downstream-only patch while we waited for -"Add native NetworkManager support (#1224)". - -Signed-off-by: Emanuele Giuseppe Esposito ---- - cloudinit/net/sysconfig.py | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py -index 2a45a4fa..dc401d78 100644 ---- a/cloudinit/net/sysconfig.py -+++ b/cloudinit/net/sysconfig.py -@@ -317,7 +317,6 @@ class Renderer(renderer.Renderer): - "ONBOOT": True, - "USERCTL": False, - "BOOTPROTO": "none", -- "AUTOCONNECT_PRIORITY": 999 - }, - "suse": {"BOOTPROTO": "static", "STARTMODE": "auto"}, - } --- -2.31.1 - diff --git a/SOURCES/ci-Revert-Use-Network-Manager-and-Netplan-as-default-re.patch b/SOURCES/ci-Revert-Use-Network-Manager-and-Netplan-as-default-re.patch deleted file mode 100644 index 28c4151..0000000 --- a/SOURCES/ci-Revert-Use-Network-Manager-and-Netplan-as-default-re.patch +++ /dev/null @@ -1,75 +0,0 @@ -From c063021168dee7937281decd8f9b601f49a7d0f3 Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Mon, 8 Aug 2022 10:02:17 +0200 -Subject: [PATCH 2/3] Revert "Use Network-Manager and Netplan as default - renderers for RHEL and Fedora (#1465)" - -RH-Author: Emanuele Giuseppe Esposito -RH-MergeRequest: 31: Revert "Revert "Setting highest autoconnect priority for network-scripts"" -RH-Commit: [2/3] bd662b768dc694c748cab9e36bc5ff0eb009e128 (eesposit/cloud-init-centos-) -RH-Bugzilla: 2107463 2104389 2117532 2098501 -RH-Acked-by: Eduardo Otubo -RH-Acked-by: Vitaly Kuznetsov -RH-Acked-by: Mohamed Gamal Morsy - -As NM is reverted, remove also documentation and any trace of it. -This reverts commit bbd9f47a7988e15a2823b065cd539d7c9562d77e. - -Signed-off-by: Emanuele Giuseppe Esposito ---- - config/cloud.cfg.tmpl | 3 --- - doc/rtd/topics/network-config.rst | 12 +----------- - 2 files changed, 1 insertion(+), 14 deletions(-) - -diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl -index f4d2fd14..80ab4f96 100644 ---- a/config/cloud.cfg.tmpl -+++ b/config/cloud.cfg.tmpl -@@ -353,7 +353,4 @@ system_info: - {% elif variant in ["dragonfly"] %} - network: - renderers: ['freebsd'] --{% elif variant in ["rhel", "fedora"] %} -- network: -- renderers: ['netplan', 'network-manager', 'networkd', 'sysconfig', 'eni'] - {% endif %} -diff --git a/doc/rtd/topics/network-config.rst b/doc/rtd/topics/network-config.rst -index f503caab..c461a3fe 100644 ---- a/doc/rtd/topics/network-config.rst -+++ b/doc/rtd/topics/network-config.rst -@@ -188,15 +188,6 @@ generated configuration into an internal network configuration state. From - this state `Cloud-init`_ delegates rendering of the configuration to Distro - supported formats. The following ``renderers`` are supported in cloud-init: - --- **NetworkManager** -- --`NetworkManager `_ is the standard Linux network --configuration tool suite. It supports a wide range of networking setups. --Configuration is typically stored in ``/etc/NetworkManager``. -- --It is the default for a number of Linux distributions, notably Fedora; --CentOS/RHEL; and derivatives. -- - - **ENI** - - /etc/network/interfaces or ``ENI`` is supported by the ``ifupdown`` package -@@ -224,7 +215,6 @@ is as follows: - - ENI - - Sysconfig - - Netplan --- NetworkManager - - When applying the policy, `Cloud-init`_ checks if the current instance has the - correct binaries and paths to support the renderer. The first renderer that -@@ -233,7 +223,7 @@ supplying an updated configuration in cloud-config. :: - - system_info: - network: -- renderers: ['netplan', 'network-manager', 'eni', 'sysconfig', 'freebsd', 'netbsd', 'openbsd'] -+ renderers: ['netplan', 'eni', 'sysconfig', 'freebsd', 'netbsd', 'openbsd'] - - - Network Configuration Tools --- -2.31.1 - diff --git a/SOURCES/ci-Support-EC2-tags-in-instance-metadata-1309.patch b/SOURCES/ci-Support-EC2-tags-in-instance-metadata-1309.patch deleted file mode 100644 index 7e2c490..0000000 --- a/SOURCES/ci-Support-EC2-tags-in-instance-metadata-1309.patch +++ /dev/null @@ -1,165 +0,0 @@ -From f5e9ed6c698eddd30e8e97d6f71070e7b75b1381 Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Mon, 30 May 2022 16:45:08 +0200 -Subject: [PATCH 1/2] Support EC2 tags in instance metadata (#1309) - -RH-Author: Emanuele Giuseppe Esposito -RH-MergeRequest: 27: Support EC2 tags in instance metadata (#1309) -RH-Commit: [1/1] f6a03e1619316959d3cd1806981b0bebf12bd3b0 (eesposit/cloud-init-centos-) -RH-Bugzilla: 2091640 -RH-Acked-by: Eduardo Otubo -RH-Acked-by: Vitaly Kuznetsov -RH-Acked-by: Mohamed Gamal Morsy - -commit 40c52ce1f4049449b04f93226721f63af874c5c7 -Author: Eduardo Dobay -Date: Wed Apr 6 01:28:01 2022 -0300 - - Support EC2 tags in instance metadata (#1309) - - Add support for newer EC2 metadata versions (up to 2021-03-23), so that - tags can be retrieved from the `ds.meta_data.tags` field, as well as - with any new fields that might have been added since the 2018-09-24 - version. - -Signed-off-by: Emanuele Giuseppe Esposito ---- - cloudinit/sources/DataSourceEc2.py | 5 +++-- - doc/rtd/topics/datasources/ec2.rst | 28 ++++++++++++++++++++++------ - tests/unittests/sources/test_ec2.py | 26 +++++++++++++++++++++++++- - tools/.github-cla-signers | 1 + - 4 files changed, 51 insertions(+), 9 deletions(-) - -diff --git a/cloudinit/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py -index 03b3870c..a030b498 100644 ---- a/cloudinit/sources/DataSourceEc2.py -+++ b/cloudinit/sources/DataSourceEc2.py -@@ -61,8 +61,9 @@ class DataSourceEc2(sources.DataSource): - min_metadata_version = "2009-04-04" - - # Priority ordered list of additional metadata versions which will be tried -- # for extended metadata content. IPv6 support comes in 2016-09-02 -- extended_metadata_versions = ["2018-09-24", "2016-09-02"] -+ # for extended metadata content. IPv6 support comes in 2016-09-02. -+ # Tags support comes in 2021-03-23. -+ extended_metadata_versions = ["2021-03-23", "2018-09-24", "2016-09-02"] - - # Setup read_url parameters per get_url_params. - url_max_wait = 120 -diff --git a/doc/rtd/topics/datasources/ec2.rst b/doc/rtd/topics/datasources/ec2.rst -index 94e4158d..77232269 100644 ---- a/doc/rtd/topics/datasources/ec2.rst -+++ b/doc/rtd/topics/datasources/ec2.rst -@@ -38,11 +38,26 @@ Userdata is accessible via the following URL: - GET http://169.254.169.254/2009-04-04/user-data - 1234,fred,reboot,true | 4512,jimbo, | 173,,, - --Note that there are multiple versions of this data provided, cloud-init --by default uses **2009-04-04** but newer versions can be supported with --relative ease (newer versions have more data exposed, while maintaining --backward compatibility with the previous versions). --Version **2016-09-02** is required for secondary IP address support. -+Note that there are multiple EC2 Metadata versions of this data provided -+to instances. cloud-init will attempt to use the most recent API version it -+supports in order to get latest API features and instance-data. If a given -+API version is not exposed to the instance, those API features will be -+unavailable to the instance. -+ -+ -++----------------+----------------------------------------------------------+ -++ EC2 version | supported instance-data/feature | -++================+==========================================================+ -++ **2021-03-23** | Required for Instance tag support. This feature must be | -+| | enabled individually on each instance. See the | -+| | `EC2 tags user guide`_. | -++----------------+----------------------------------------------------------+ -+| **2016-09-02** | Required for secondary IP address support. | -++----------------+----------------------------------------------------------+ -+| **2009-04-04** | Minimum supports EC2 API version for meta-data and | -+| | user-data. | -++----------------+----------------------------------------------------------+ -+ - - To see which versions are supported from your cloud provider use the following - URL: -@@ -71,7 +86,7 @@ configuration (in `/etc/cloud/cloud.cfg` or `/etc/cloud/cloud.cfg.d/`). - - The settings that may be configured are: - -- * **metadata_urls**: This list of urls will be searched for an Ec2 -+ * **metadata_urls**: This list of urls will be searched for an EC2 - metadata service. The first entry that successfully returns a 200 response - for //meta-data/instance-id will be selected. - (default: ['http://169.254.169.254', 'http://instance-data:8773']). -@@ -121,4 +136,5 @@ Notes - For example: the primary NIC will have a DHCP route-metric of 100, - the next NIC will be 200. - -+.. _EC2 tags user guide: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS - .. vi: textwidth=79 -diff --git a/tests/unittests/sources/test_ec2.py b/tests/unittests/sources/test_ec2.py -index b376660d..7c8a5ea5 100644 ---- a/tests/unittests/sources/test_ec2.py -+++ b/tests/unittests/sources/test_ec2.py -@@ -210,6 +210,17 @@ SECONDARY_IP_METADATA_2018_09_24 = { - - M_PATH_NET = "cloudinit.sources.DataSourceEc2.net." - -+TAGS_METADATA_2021_03_23 = { -+ **DEFAULT_METADATA, -+ "tags": { -+ "instance": { -+ "Environment": "production", -+ "Application": "test", -+ "TagWithoutValue": "", -+ } -+ }, -+} -+ - - def _register_ssh_keys(rfunc, base_url, keys_data): - """handle ssh key inconsistencies. -@@ -670,7 +681,7 @@ class TestEc2(test_helpers.HttprettyTestCase): - logs_with_redacted = [log for log in all_logs if REDACT_TOK in log] - logs_with_token = [log for log in all_logs if "API-TOKEN" in log] - self.assertEqual(1, len(logs_with_redacted_ttl)) -- self.assertEqual(81, len(logs_with_redacted)) -+ self.assertEqual(83, len(logs_with_redacted)) - self.assertEqual(0, len(logs_with_token)) - - @mock.patch("cloudinit.net.dhcp.maybe_perform_dhcp_discovery") -@@ -811,6 +822,19 @@ class TestEc2(test_helpers.HttprettyTestCase): - ) - self.assertIn("Crawl of metadata service took", self.logs.getvalue()) - -+ def test_get_instance_tags(self): -+ ds = self._setup_ds( -+ platform_data=self.valid_platform_data, -+ sys_cfg={"datasource": {"Ec2": {"strict_id": False}}}, -+ md={"md": TAGS_METADATA_2021_03_23}, -+ ) -+ self.assertTrue(ds.get_data()) -+ self.assertIn("tags", ds.metadata) -+ self.assertIn("instance", ds.metadata["tags"]) -+ instance_tags = ds.metadata["tags"]["instance"] -+ self.assertEqual(instance_tags["Application"], "test") -+ self.assertEqual(instance_tags["Environment"], "production") -+ - - class TestGetSecondaryAddresses(test_helpers.CiTestCase): - -diff --git a/tools/.github-cla-signers b/tools/.github-cla-signers -index ac157a2f..9f71ea0c 100644 ---- a/tools/.github-cla-signers -+++ b/tools/.github-cla-signers -@@ -26,6 +26,7 @@ dermotbradley - dhensby - eandersson - eb3095 -+edudobay - emmanuelthome - eslerm - esposem --- -2.31.1 - diff --git a/SOURCES/ci-Use-Network-Manager-and-Netplan-as-default-renderers.patch b/SOURCES/ci-Use-Network-Manager-and-Netplan-as-default-renderers.patch deleted file mode 100644 index 553d8fc..0000000 --- a/SOURCES/ci-Use-Network-Manager-and-Netplan-as-default-renderers.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 840d6f7ca86fe9822c613f0f2c21f136271ce3b6 Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Thu, 19 May 2022 15:44:03 +0200 -Subject: [PATCH 2/5] Use Network-Manager and Netplan as default renderers for - RHEL and Fedora (#1465) - -RH-Author: Emanuele Giuseppe Esposito -RH-MergeRequest: 24: Add native NetworkManager support (#1224) -RH-Commit: [2/3] e33081b15a8558967bb480ed659116e7e0872840 (eesposit/cloud-init-centos-) -RH-Bugzilla: 2056964 -RH-Acked-by: Miroslav Rezanina -RH-Acked-by: Vitaly Kuznetsov - -commit 7703aa98b89c8daba207c28a0422268ead10019a -Author: Emanuele Giuseppe Esposito -Date: Thu May 19 15:05:01 2022 +0200 - - Use Network-Manager and Netplan as default renderers for RHEL and Fedora (#1465) - - This is adapted from Neal Gompa's PR: - https://github.com/canonical/cloud-init/pull/1435 - - The only difference is that we are not modifying renderers.py (thus - modifying the priority of all distros), but just tweaking cloud.cfg to - apply this change to Fedora and RHEL. Other distros can optionally - add themselves afterwards. - - net: Prefer Netplan and NetworkManager renderers by default - - NetworkManager is used by default on a variety of Linux distributions, - and exists as a cross-distribution network management service. - - Additionally, add information about the NetworkManager renderer to - the cloud-init documentation. - - Because Netplan can be explicitly used to manage NetworkManager, - it needs to be preferred before NetworkManager. - - This change is a follow-up to #1224, which added the native - NetworkManager renderer. - This patch has been deployed on Fedora's cloud-init package throughout - the development of Fedora Linux 36 to verify that it works. - - This should also make it tremendously easier for Linux distributions - to use cloud-init because now a standard configuration is supported - by default. - - Signed-off-by: Neal Gompa - - Signed-off-by: Emanuele Giuseppe Esposito - -Signed-off-by: Emanuele Giuseppe Esposito ---- - config/cloud.cfg.tmpl | 3 +++ - doc/rtd/topics/network-config.rst | 12 +++++++++++- - 2 files changed, 14 insertions(+), 1 deletion(-) - -diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl -index fb4b456c..86beee3c 100644 ---- a/config/cloud.cfg.tmpl -+++ b/config/cloud.cfg.tmpl -@@ -330,4 +330,7 @@ system_info: - {% elif variant in ["dragonfly"] %} - network: - renderers: ['freebsd'] -+{% elif variant in ["rhel", "fedora"] %} -+ network: -+ renderers: ['netplan', 'network-manager', 'networkd', 'sysconfig', 'eni'] - {% endif %} -diff --git a/doc/rtd/topics/network-config.rst b/doc/rtd/topics/network-config.rst -index c461a3fe..f503caab 100644 ---- a/doc/rtd/topics/network-config.rst -+++ b/doc/rtd/topics/network-config.rst -@@ -188,6 +188,15 @@ generated configuration into an internal network configuration state. From - this state `Cloud-init`_ delegates rendering of the configuration to Distro - supported formats. The following ``renderers`` are supported in cloud-init: - -+- **NetworkManager** -+ -+`NetworkManager `_ is the standard Linux network -+configuration tool suite. It supports a wide range of networking setups. -+Configuration is typically stored in ``/etc/NetworkManager``. -+ -+It is the default for a number of Linux distributions, notably Fedora; -+CentOS/RHEL; and derivatives. -+ - - **ENI** - - /etc/network/interfaces or ``ENI`` is supported by the ``ifupdown`` package -@@ -215,6 +224,7 @@ is as follows: - - ENI - - Sysconfig - - Netplan -+- NetworkManager - - When applying the policy, `Cloud-init`_ checks if the current instance has the - correct binaries and paths to support the renderer. The first renderer that -@@ -223,7 +233,7 @@ supplying an updated configuration in cloud-config. :: - - system_info: - network: -- renderers: ['netplan', 'eni', 'sysconfig', 'freebsd', 'netbsd', 'openbsd'] -+ renderers: ['netplan', 'network-manager', 'eni', 'sysconfig', 'freebsd', 'netbsd', 'openbsd'] - - - Network Configuration Tools --- -2.31.1 - diff --git a/SOURCES/ci-cc_set_hostname-do-not-write-localhost-when-no-hostn.patch b/SOURCES/ci-cc_set_hostname-do-not-write-localhost-when-no-hostn.patch deleted file mode 100644 index a307e68..0000000 --- a/SOURCES/ci-cc_set_hostname-do-not-write-localhost-when-no-hostn.patch +++ /dev/null @@ -1,801 +0,0 @@ -From d1790e6462e509e3cd87fc449df84fbd02ca1d89 Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Thu, 2 Jun 2022 16:03:43 +0200 -Subject: [PATCH 2/2] cc_set_hostname: do not write "localhost" when no - hostname is given (#1453) - -RH-Author: Emanuele Giuseppe Esposito -RH-MergeRequest: 28: cc_set_hostname: do not write "localhost" when no hostname is given (#1453) -RH-Commit: [1/1] 4370e9149371dc89be82cb05d30d33e4d2638cec (eesposit/cloud-init-centos-) -RH-Bugzilla: 1980403 -RH-Acked-by: Miroslav Rezanina -RH-Acked-by: Mohamed Gamal Morsy - -commit 74e43496f353db52e15d96abeb54ad63baac5be9 -Author: Emanuele Giuseppe Esposito -Date: Tue May 31 16:03:44 2022 +0200 - - cc_set_hostname: do not write "localhost" when no hostname is given (#1453) - - Systemd used to sometimes ignore localhost in /etc/hostnames, and many programs - like cloud-init used this as a workaround to set a default hostname. - - From https://github.com/systemd/systemd/commit/d39079fcaa05e23540d2b1f0270fa31c22a7e9f1: - - We would sometimes ignore localhost-style names in /etc/hostname. That is - brittle. If the user configured some hostname, it's most likely because they - want to use that as the hostname. If they don't want to use such a hostname, - they should just not create the config. Everything becomes simples if we just - use the configured hostname as-is. - - This behaviour seems to have been a workaround for Anaconda installer and other - tools writing out /etc/hostname with the default of "localhost.localdomain". - Anaconda PR to stop doing that: rhinstaller/anaconda#3040. - That might have been useful as a work-around for other programs misbehaving if - /etc/hostname was not present, but nowadays it's not useful because systemd - mostly controls the hostname and it is perfectly happy without that file. - - Apart from making things simpler, this allows users to set a hostname like - "localhost" and have it honoured, if such a whim strikes them. - - As also suggested by the Anaconda PR, we need to stop writing default "localhost" - in /etc/hostnames, and let the right service (networking, user) do that if they - need to. Otherwise, "localhost" will permanently stay as hostname and will - prevent other tools like NetworkManager from setting the right one. - - Signed-off-by: Emanuele Giuseppe Esposito - - RHBZ: 1980403 - -Conflicts: - cloudinit/config/cc_update_etc_hosts.py - cloudinit/sources/DataSourceCloudSigma.py - cloudinit/util.py - tests/unittests/test_util.py - Additional imports and/or conditionals that are not present in this version - -Signed-off-by: Emanuele Giuseppe Esposito ---- - cloudinit/cmd/main.py | 2 +- - cloudinit/config/cc_apt_configure.py | 2 +- - cloudinit/config/cc_debug.py | 2 +- - cloudinit/config/cc_phone_home.py | 4 +- - cloudinit/config/cc_set_hostname.py | 6 ++- - cloudinit/config/cc_spacewalk.py | 2 +- - cloudinit/config/cc_update_etc_hosts.py | 4 +- - cloudinit/config/cc_update_hostname.py | 7 +++- - cloudinit/sources/DataSourceAliYun.py | 8 +++- - cloudinit/sources/DataSourceCloudSigma.py | 6 ++- - cloudinit/sources/DataSourceGCE.py | 5 ++- - cloudinit/sources/DataSourceScaleway.py | 3 +- - cloudinit/sources/__init__.py | 28 ++++++++++--- - cloudinit/util.py | 29 +++++++++++--- - .../unittests/config/test_cc_set_hostname.py | 40 ++++++++++++++++++- - tests/unittests/sources/test_aliyun.py | 2 +- - tests/unittests/sources/test_cloudsigma.py | 8 ++-- - tests/unittests/sources/test_digitalocean.py | 2 +- - tests/unittests/sources/test_gce.py | 4 +- - tests/unittests/sources/test_hetzner.py | 2 +- - tests/unittests/sources/test_init.py | 29 +++++++++----- - tests/unittests/sources/test_scaleway.py | 2 +- - tests/unittests/sources/test_vmware.py | 4 +- - tests/unittests/test_util.py | 17 ++++---- - tests/unittests/util.py | 3 +- - 25 files changed, 166 insertions(+), 55 deletions(-) - -diff --git a/cloudinit/cmd/main.py b/cloudinit/cmd/main.py -index c9be41b3..816d31aa 100644 ---- a/cloudinit/cmd/main.py -+++ b/cloudinit/cmd/main.py -@@ -813,7 +813,7 @@ def _maybe_set_hostname(init, stage, retry_stage): - @param retry_stage: String represented logs upon error setting hostname. - """ - cloud = init.cloudify() -- (hostname, _fqdn) = util.get_hostname_fqdn( -+ (hostname, _fqdn, _) = util.get_hostname_fqdn( - init.cfg, cloud, metadata_only=True - ) - if hostname: # meta-data or user-data hostname content -diff --git a/cloudinit/config/cc_apt_configure.py b/cloudinit/config/cc_apt_configure.py -index c558311a..0e6466ec 100644 ---- a/cloudinit/config/cc_apt_configure.py -+++ b/cloudinit/config/cc_apt_configure.py -@@ -753,7 +753,7 @@ def search_for_mirror_dns(configured, mirrortype, cfg, cloud): - raise ValueError("unknown mirror type") - - # if we have a fqdn, then search its domain portion first -- (_, fqdn) = util.get_hostname_fqdn(cfg, cloud) -+ fqdn = util.get_hostname_fqdn(cfg, cloud).fqdn - mydom = ".".join(fqdn.split(".")[1:]) - if mydom: - doms.append(".%s" % mydom) -diff --git a/cloudinit/config/cc_debug.py b/cloudinit/config/cc_debug.py -index c51818c3..a00f2823 100644 ---- a/cloudinit/config/cc_debug.py -+++ b/cloudinit/config/cc_debug.py -@@ -95,7 +95,7 @@ def handle(name, cfg, cloud, log, args): - "Datasource: %s\n" % (type_utils.obj_name(cloud.datasource)) - ) - to_print.write("Distro: %s\n" % (type_utils.obj_name(cloud.distro))) -- to_print.write("Hostname: %s\n" % (cloud.get_hostname(True))) -+ to_print.write("Hostname: %s\n" % (cloud.get_hostname(True).hostname)) - to_print.write("Instance ID: %s\n" % (cloud.get_instance_id())) - to_print.write("Locale: %s\n" % (cloud.get_locale())) - to_print.write("Launch IDX: %s\n" % (cloud.launch_index)) -diff --git a/cloudinit/config/cc_phone_home.py b/cloudinit/config/cc_phone_home.py -index a0e1da78..1cf270aa 100644 ---- a/cloudinit/config/cc_phone_home.py -+++ b/cloudinit/config/cc_phone_home.py -@@ -119,8 +119,8 @@ def handle(name, cfg, cloud, log, args): - - all_keys = {} - all_keys["instance_id"] = cloud.get_instance_id() -- all_keys["hostname"] = cloud.get_hostname() -- all_keys["fqdn"] = cloud.get_hostname(fqdn=True) -+ all_keys["hostname"] = cloud.get_hostname().hostname -+ all_keys["fqdn"] = cloud.get_hostname(fqdn=True).hostname - - pubkeys = { - "pub_key_dsa": "/etc/ssh/ssh_host_dsa_key.pub", -diff --git a/cloudinit/config/cc_set_hostname.py b/cloudinit/config/cc_set_hostname.py -index eb0ca328..2674fa20 100644 ---- a/cloudinit/config/cc_set_hostname.py -+++ b/cloudinit/config/cc_set_hostname.py -@@ -76,7 +76,7 @@ def handle(name, cfg, cloud, log, _args): - if hostname_fqdn is not None: - cloud.distro.set_option("prefer_fqdn_over_hostname", hostname_fqdn) - -- (hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud) -+ (hostname, fqdn, is_default) = util.get_hostname_fqdn(cfg, cloud) - # Check for previous successful invocation of set-hostname - - # set-hostname artifact file accounts for both hostname and fqdn -@@ -94,6 +94,10 @@ def handle(name, cfg, cloud, log, _args): - if not hostname_changed: - log.debug("No hostname changes. Skipping set-hostname") - return -+ if is_default and hostname == "localhost": -+ # https://github.com/systemd/systemd/commit/d39079fcaa05e23540d2b1f0270fa31c22a7e9f1 -+ log.debug("Hostname is localhost. Let other services handle this.") -+ return - log.debug("Setting the hostname to %s (%s)", fqdn, hostname) - try: - cloud.distro.set_hostname(hostname, fqdn) -diff --git a/cloudinit/config/cc_spacewalk.py b/cloudinit/config/cc_spacewalk.py -index 3fa6c388..419c8b32 100644 ---- a/cloudinit/config/cc_spacewalk.py -+++ b/cloudinit/config/cc_spacewalk.py -@@ -89,7 +89,7 @@ def handle(name, cfg, cloud, log, _args): - if not is_registered(): - do_register( - spacewalk_server, -- cloud.datasource.get_hostname(fqdn=True), -+ cloud.datasource.get_hostname(fqdn=True).hostname, - proxy=cfg.get("proxy"), - log=log, - activation_key=cfg.get("activation_key"), -diff --git a/cloudinit/config/cc_update_etc_hosts.py b/cloudinit/config/cc_update_etc_hosts.py -index f0aa9b0f..d2ee6f45 100644 ---- a/cloudinit/config/cc_update_etc_hosts.py -+++ b/cloudinit/config/cc_update_etc_hosts.py -@@ -62,7 +62,7 @@ def handle(name, cfg, cloud, log, _args): - hosts_fn = cloud.distro.hosts_fn - - if util.translate_bool(manage_hosts, addons=["template"]): -- (hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud) -+ (hostname, fqdn, _) = util.get_hostname_fqdn(cfg, cloud) - if not hostname: - log.warning( - "Option 'manage_etc_hosts' was set, but no hostname was found" -@@ -84,7 +84,7 @@ def handle(name, cfg, cloud, log, _args): - ) - - elif manage_hosts == "localhost": -- (hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud) -+ (hostname, fqdn, _) = util.get_hostname_fqdn(cfg, cloud) - if not hostname: - log.warning( - "Option 'manage_etc_hosts' was set, but no hostname was found" -diff --git a/cloudinit/config/cc_update_hostname.py b/cloudinit/config/cc_update_hostname.py -index 09f6f6da..e2046020 100644 ---- a/cloudinit/config/cc_update_hostname.py -+++ b/cloudinit/config/cc_update_hostname.py -@@ -56,7 +56,12 @@ def handle(name, cfg, cloud, log, _args): - if hostname_fqdn is not None: - cloud.distro.set_option("prefer_fqdn_over_hostname", hostname_fqdn) - -- (hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud) -+ (hostname, fqdn, is_default) = util.get_hostname_fqdn(cfg, cloud) -+ if is_default and hostname == "localhost": -+ # https://github.com/systemd/systemd/commit/d39079fcaa05e23540d2b1f0270fa31c22a7e9f1 -+ log.debug("Hostname is localhost. Let other services handle this.") -+ return -+ - try: - prev_fn = os.path.join(cloud.get_cpath("data"), "previous-hostname") - log.debug("Updating hostname to %s (%s)", fqdn, hostname) -diff --git a/cloudinit/sources/DataSourceAliYun.py b/cloudinit/sources/DataSourceAliYun.py -index 37f512e3..b9390aca 100644 ---- a/cloudinit/sources/DataSourceAliYun.py -+++ b/cloudinit/sources/DataSourceAliYun.py -@@ -2,6 +2,7 @@ - - from cloudinit import dmi, sources - from cloudinit.sources import DataSourceEc2 as EC2 -+from cloudinit.sources import DataSourceHostname - - ALIYUN_PRODUCT = "Alibaba Cloud ECS" - -@@ -16,7 +17,12 @@ class DataSourceAliYun(EC2.DataSourceEc2): - extended_metadata_versions = [] - - def get_hostname(self, fqdn=False, resolve_ip=False, metadata_only=False): -- return self.metadata.get("hostname", "localhost.localdomain") -+ hostname = self.metadata.get("hostname") -+ is_default = False -+ if hostname is None: -+ hostname = "localhost.localdomain" -+ is_default = True -+ return DataSourceHostname(hostname, is_default) - - def get_public_ssh_keys(self): - return parse_public_keys(self.metadata.get("public-keys", {})) -diff --git a/cloudinit/sources/DataSourceCloudSigma.py b/cloudinit/sources/DataSourceCloudSigma.py -index de71c3e9..91ebb084 100644 ---- a/cloudinit/sources/DataSourceCloudSigma.py -+++ b/cloudinit/sources/DataSourceCloudSigma.py -@@ -11,6 +11,7 @@ from cloudinit import dmi - from cloudinit import log as logging - from cloudinit import sources - from cloudinit.cs_utils import SERIAL_PORT, Cepko -+from cloudinit.sources import DataSourceHostname - - LOG = logging.getLogger(__name__) - -@@ -90,9 +91,10 @@ class DataSourceCloudSigma(sources.DataSource): - the first part from uuid is being used. - """ - if re.match(r"^[A-Za-z0-9 -_\.]+$", self.metadata["name"]): -- return self.metadata["name"][:61] -+ ret = self.metadata["name"][:61] - else: -- return self.metadata["uuid"].split("-")[0] -+ ret = self.metadata["uuid"].split("-")[0] -+ return DataSourceHostname(ret, False) - - def get_public_ssh_keys(self): - return [self.ssh_public_key] -diff --git a/cloudinit/sources/DataSourceGCE.py b/cloudinit/sources/DataSourceGCE.py -index c470bea8..f7ec6b52 100644 ---- a/cloudinit/sources/DataSourceGCE.py -+++ b/cloudinit/sources/DataSourceGCE.py -@@ -12,6 +12,7 @@ from cloudinit import log as logging - from cloudinit import sources, url_helper, util - from cloudinit.distros import ug_util - from cloudinit.net.dhcp import EphemeralDHCPv4 -+from cloudinit.sources import DataSourceHostname - - LOG = logging.getLogger(__name__) - -@@ -122,7 +123,9 @@ class DataSourceGCE(sources.DataSource): - - def get_hostname(self, fqdn=False, resolve_ip=False, metadata_only=False): - # GCE has long FDQN's and has asked for short hostnames. -- return self.metadata["local-hostname"].split(".")[0] -+ return DataSourceHostname( -+ self.metadata["local-hostname"].split(".")[0], False -+ ) - - @property - def availability_zone(self): -diff --git a/cloudinit/sources/DataSourceScaleway.py b/cloudinit/sources/DataSourceScaleway.py -index 8e5dd82c..8f08dc6d 100644 ---- a/cloudinit/sources/DataSourceScaleway.py -+++ b/cloudinit/sources/DataSourceScaleway.py -@@ -30,6 +30,7 @@ from cloudinit import log as logging - from cloudinit import net, sources, url_helper, util - from cloudinit.event import EventScope, EventType - from cloudinit.net.dhcp import EphemeralDHCPv4, NoDHCPLeaseError -+from cloudinit.sources import DataSourceHostname - - LOG = logging.getLogger(__name__) - -@@ -282,7 +283,7 @@ class DataSourceScaleway(sources.DataSource): - return ssh_keys - - def get_hostname(self, fqdn=False, resolve_ip=False, metadata_only=False): -- return self.metadata["hostname"] -+ return DataSourceHostname(self.metadata["hostname"], False) - - @property - def availability_zone(self): -diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py -index 88028cfa..77b24fd7 100644 ---- a/cloudinit/sources/__init__.py -+++ b/cloudinit/sources/__init__.py -@@ -148,6 +148,11 @@ URLParams = namedtuple( - ], - ) - -+DataSourceHostname = namedtuple( -+ "DataSourceHostname", -+ ["hostname", "is_default"], -+) -+ - - class DataSource(CloudInitPickleMixin, metaclass=abc.ABCMeta): - -@@ -291,7 +296,7 @@ class DataSource(CloudInitPickleMixin, metaclass=abc.ABCMeta): - - def _get_standardized_metadata(self, instance_data): - """Return a dictionary of standardized metadata keys.""" -- local_hostname = self.get_hostname() -+ local_hostname = self.get_hostname().hostname - instance_id = self.get_instance_id() - availability_zone = self.availability_zone - # In the event of upgrade from existing cloudinit, pickled datasource -@@ -697,22 +702,33 @@ class DataSource(CloudInitPickleMixin, metaclass=abc.ABCMeta): - @param metadata_only: Boolean, set True to avoid looking up hostname - if meta-data doesn't have local-hostname present. - -- @return: hostname or qualified hostname. Optionally return None when -+ @return: a DataSourceHostname namedtuple -+ , (str, bool). -+ is_default is a bool and -+ it's true only if hostname is localhost and was -+ returned by util.get_hostname() as a default. -+ This is used to differentiate with a user-defined -+ localhost hostname. -+ Optionally return (None, False) when - metadata_only is True and local-hostname data is not available. - """ - defdomain = "localdomain" - defhost = "localhost" - domain = defdomain -+ is_default = False - - if not self.metadata or not self.metadata.get("local-hostname"): - if metadata_only: -- return None -+ return DataSourceHostname(None, is_default) - # this is somewhat questionable really. - # the cloud datasource was asked for a hostname - # and didn't have one. raising error might be more appropriate - # but instead, basically look up the existing hostname - toks = [] - hostname = util.get_hostname() -+ if hostname == "localhost": -+ # default hostname provided by socket.gethostname() -+ is_default = True - hosts_fqdn = util.get_fqdn_from_hosts(hostname) - if hosts_fqdn and hosts_fqdn.find(".") > 0: - toks = str(hosts_fqdn).split(".") -@@ -745,9 +761,9 @@ class DataSource(CloudInitPickleMixin, metaclass=abc.ABCMeta): - hostname = toks[0] - - if fqdn and domain != defdomain: -- return "%s.%s" % (hostname, domain) -- else: -- return hostname -+ hostname = "%s.%s" % (hostname, domain) -+ -+ return DataSourceHostname(hostname, is_default) - - def get_package_mirror_info(self): - return self.distro.get_package_mirror_info(data_source=self) -diff --git a/cloudinit/util.py b/cloudinit/util.py -index 569fc215..4cb21551 100644 ---- a/cloudinit/util.py -+++ b/cloudinit/util.py -@@ -32,7 +32,8 @@ import subprocess - import sys - import time - from base64 import b64decode, b64encode --from errno import ENOENT -+from collections import deque, namedtuple -+from errno import EACCES, ENOENT - from functools import lru_cache - from typing import List - from urllib import parse -@@ -1072,6 +1073,12 @@ def dos2unix(contents): - return contents.replace("\r\n", "\n") - - -+HostnameFqdnInfo = namedtuple( -+ "HostnameFqdnInfo", -+ ["hostname", "fqdn", "is_default"], -+) -+ -+ - def get_hostname_fqdn(cfg, cloud, metadata_only=False): - """Get hostname and fqdn from config if present and fallback to cloud. - -@@ -1079,9 +1086,17 @@ def get_hostname_fqdn(cfg, cloud, metadata_only=False): - @param cloud: Cloud instance from init.cloudify(). - @param metadata_only: Boolean, set True to only query cloud meta-data, - returning None if not present in meta-data. -- @return: a Tuple of strings , . Values can be none when -+ @return: a namedtuple of -+ , , (str, str, bool). -+ Values can be none when - metadata_only is True and no cfg or metadata provides hostname info. -+ is_default is a bool and -+ it's true only if hostname is localhost and was -+ returned by util.get_hostname() as a default. -+ This is used to differentiate with a user-defined -+ localhost hostname. - """ -+ is_default = False - if "fqdn" in cfg: - # user specified a fqdn. Default hostname then is based off that - fqdn = cfg["fqdn"] -@@ -1095,12 +1110,16 @@ def get_hostname_fqdn(cfg, cloud, metadata_only=False): - else: - # no fqdn set, get fqdn from cloud. - # get hostname from cfg if available otherwise cloud -- fqdn = cloud.get_hostname(fqdn=True, metadata_only=metadata_only) -+ fqdn = cloud.get_hostname( -+ fqdn=True, metadata_only=metadata_only -+ ).hostname - if "hostname" in cfg: - hostname = cfg["hostname"] - else: -- hostname = cloud.get_hostname(metadata_only=metadata_only) -- return (hostname, fqdn) -+ hostname, is_default = cloud.get_hostname( -+ metadata_only=metadata_only -+ ) -+ return HostnameFqdnInfo(hostname, fqdn, is_default) - - - def get_fqdn_from_hosts(hostname, filename="/etc/hosts"): -diff --git a/tests/unittests/config/test_cc_set_hostname.py b/tests/unittests/config/test_cc_set_hostname.py -index fd994c4e..3d1d86ee 100644 ---- a/tests/unittests/config/test_cc_set_hostname.py -+++ b/tests/unittests/config/test_cc_set_hostname.py -@@ -11,6 +11,7 @@ from configobj import ConfigObj - - from cloudinit import cloud, distros, helpers, util - from cloudinit.config import cc_set_hostname -+from cloudinit.sources import DataSourceNone - from tests.unittests import helpers as t_help - - LOG = logging.getLogger(__name__) -@@ -153,7 +154,8 @@ class TestHostname(t_help.FilesystemMockingTestCase): - ) - ] not in m_subp.call_args_list - -- def test_multiple_calls_skips_unchanged_hostname(self): -+ @mock.patch("cloudinit.util.get_hostname", return_value="localhost") -+ def test_multiple_calls_skips_unchanged_hostname(self, get_hostname): - """Only new hostname or fqdn values will generate a hostname call.""" - distro = self._fetch_distro("debian") - paths = helpers.Paths({"cloud_dir": self.tmp}) -@@ -182,6 +184,42 @@ class TestHostname(t_help.FilesystemMockingTestCase): - self.logs.getvalue(), - ) - -+ @mock.patch("cloudinit.util.get_hostname", return_value="localhost") -+ def test_localhost_default_hostname(self, get_hostname): -+ """ -+ No hostname set. Default value returned is localhost, -+ but we shouldn't write it in /etc/hostname -+ """ -+ distro = self._fetch_distro("debian") -+ paths = helpers.Paths({"cloud_dir": self.tmp}) -+ ds = DataSourceNone.DataSourceNone({}, None, paths) -+ cc = cloud.Cloud(ds, paths, {}, distro, None) -+ self.patchUtils(self.tmp) -+ -+ util.write_file("/etc/hostname", "") -+ cc_set_hostname.handle("cc_set_hostname", {}, cc, LOG, []) -+ contents = util.load_file("/etc/hostname") -+ self.assertEqual("", contents.strip()) -+ -+ @mock.patch("cloudinit.util.get_hostname", return_value="localhost") -+ def test_localhost_user_given_hostname(self, get_hostname): -+ """ -+ User set hostname is localhost. We should write it in /etc/hostname -+ """ -+ distro = self._fetch_distro("debian") -+ paths = helpers.Paths({"cloud_dir": self.tmp}) -+ ds = DataSourceNone.DataSourceNone({}, None, paths) -+ cc = cloud.Cloud(ds, paths, {}, distro, None) -+ self.patchUtils(self.tmp) -+ -+ # user-provided localhost should not be ignored -+ util.write_file("/etc/hostname", "") -+ cc_set_hostname.handle( -+ "cc_set_hostname", {"hostname": "localhost"}, cc, LOG, [] -+ ) -+ contents = util.load_file("/etc/hostname") -+ self.assertEqual("localhost", contents.strip()) -+ - def test_error_on_distro_set_hostname_errors(self): - """Raise SetHostnameError on exceptions from distro.set_hostname.""" - distro = self._fetch_distro("debian") -diff --git a/tests/unittests/sources/test_aliyun.py b/tests/unittests/sources/test_aliyun.py -index 8a61d5ee..e628dc02 100644 ---- a/tests/unittests/sources/test_aliyun.py -+++ b/tests/unittests/sources/test_aliyun.py -@@ -149,7 +149,7 @@ class TestAliYunDatasource(test_helpers.HttprettyTestCase): - - def _test_host_name(self): - self.assertEqual( -- self.default_metadata["hostname"], self.ds.get_hostname() -+ self.default_metadata["hostname"], self.ds.get_hostname().hostname - ) - - @mock.patch("cloudinit.sources.DataSourceAliYun._is_aliyun") -diff --git a/tests/unittests/sources/test_cloudsigma.py b/tests/unittests/sources/test_cloudsigma.py -index a2f26245..3dca7ea8 100644 ---- a/tests/unittests/sources/test_cloudsigma.py -+++ b/tests/unittests/sources/test_cloudsigma.py -@@ -58,12 +58,14 @@ class DataSourceCloudSigmaTest(test_helpers.CiTestCase): - - def test_get_hostname(self): - self.datasource.get_data() -- self.assertEqual("test_server", self.datasource.get_hostname()) -+ self.assertEqual( -+ "test_server", self.datasource.get_hostname().hostname -+ ) - self.datasource.metadata["name"] = "" -- self.assertEqual("65b2fb23", self.datasource.get_hostname()) -+ self.assertEqual("65b2fb23", self.datasource.get_hostname().hostname) - utf8_hostname = b"\xd1\x82\xd0\xb5\xd1\x81\xd1\x82".decode("utf-8") - self.datasource.metadata["name"] = utf8_hostname -- self.assertEqual("65b2fb23", self.datasource.get_hostname()) -+ self.assertEqual("65b2fb23", self.datasource.get_hostname().hostname) - - def test_get_public_ssh_keys(self): - self.datasource.get_data() -diff --git a/tests/unittests/sources/test_digitalocean.py b/tests/unittests/sources/test_digitalocean.py -index f3e6224e..47e46c66 100644 ---- a/tests/unittests/sources/test_digitalocean.py -+++ b/tests/unittests/sources/test_digitalocean.py -@@ -178,7 +178,7 @@ class TestDataSourceDigitalOcean(CiTestCase): - self.assertEqual(DO_META.get("vendor_data"), ds.get_vendordata_raw()) - self.assertEqual(DO_META.get("region"), ds.availability_zone) - self.assertEqual(DO_META.get("droplet_id"), ds.get_instance_id()) -- self.assertEqual(DO_META.get("hostname"), ds.get_hostname()) -+ self.assertEqual(DO_META.get("hostname"), ds.get_hostname().hostname) - - # Single key - self.assertEqual( -diff --git a/tests/unittests/sources/test_gce.py b/tests/unittests/sources/test_gce.py -index e030931b..1ce0c6ec 100644 ---- a/tests/unittests/sources/test_gce.py -+++ b/tests/unittests/sources/test_gce.py -@@ -126,7 +126,7 @@ class TestDataSourceGCE(test_helpers.HttprettyTestCase): - self.ds.get_data() - - shostname = GCE_META.get("instance/hostname").split(".")[0] -- self.assertEqual(shostname, self.ds.get_hostname()) -+ self.assertEqual(shostname, self.ds.get_hostname().hostname) - - self.assertEqual( - GCE_META.get("instance/id"), self.ds.get_instance_id() -@@ -147,7 +147,7 @@ class TestDataSourceGCE(test_helpers.HttprettyTestCase): - ) - - shostname = GCE_META_PARTIAL.get("instance/hostname").split(".")[0] -- self.assertEqual(shostname, self.ds.get_hostname()) -+ self.assertEqual(shostname, self.ds.get_hostname().hostname) - - def test_userdata_no_encoding(self): - """check that user-data is read.""" -diff --git a/tests/unittests/sources/test_hetzner.py b/tests/unittests/sources/test_hetzner.py -index f80ed45f..193b7e42 100644 ---- a/tests/unittests/sources/test_hetzner.py -+++ b/tests/unittests/sources/test_hetzner.py -@@ -116,7 +116,7 @@ class TestDataSourceHetzner(CiTestCase): - - self.assertTrue(m_readmd.called) - -- self.assertEqual(METADATA.get("hostname"), ds.get_hostname()) -+ self.assertEqual(METADATA.get("hostname"), ds.get_hostname().hostname) - - self.assertEqual(METADATA.get("public-keys"), ds.get_public_ssh_keys()) - -diff --git a/tests/unittests/sources/test_init.py b/tests/unittests/sources/test_init.py -index ce8fc970..79fc9c5b 100644 ---- a/tests/unittests/sources/test_init.py -+++ b/tests/unittests/sources/test_init.py -@@ -272,9 +272,11 @@ class TestDataSource(CiTestCase): - self.assertEqual( - "test-subclass-hostname", datasource.metadata["local-hostname"] - ) -- self.assertEqual("test-subclass-hostname", datasource.get_hostname()) -+ self.assertEqual( -+ "test-subclass-hostname", datasource.get_hostname().hostname -+ ) - datasource.metadata["local-hostname"] = "hostname.my.domain.com" -- self.assertEqual("hostname", datasource.get_hostname()) -+ self.assertEqual("hostname", datasource.get_hostname().hostname) - - def test_get_hostname_with_fqdn_returns_local_hostname_with_domain(self): - """Datasource.get_hostname with fqdn set gets qualified hostname.""" -@@ -285,7 +287,8 @@ class TestDataSource(CiTestCase): - self.assertTrue(datasource.get_data()) - datasource.metadata["local-hostname"] = "hostname.my.domain.com" - self.assertEqual( -- "hostname.my.domain.com", datasource.get_hostname(fqdn=True) -+ "hostname.my.domain.com", -+ datasource.get_hostname(fqdn=True).hostname, - ) - - def test_get_hostname_without_metadata_uses_system_hostname(self): -@@ -300,10 +303,12 @@ class TestDataSource(CiTestCase): - with mock.patch(mock_fqdn) as m_fqdn: - m_gethost.return_value = "systemhostname.domain.com" - m_fqdn.return_value = None # No maching fqdn in /etc/hosts -- self.assertEqual("systemhostname", datasource.get_hostname()) -+ self.assertEqual( -+ "systemhostname", datasource.get_hostname().hostname -+ ) - self.assertEqual( - "systemhostname.domain.com", -- datasource.get_hostname(fqdn=True), -+ datasource.get_hostname(fqdn=True).hostname, - ) - - def test_get_hostname_without_metadata_returns_none(self): -@@ -316,9 +321,13 @@ class TestDataSource(CiTestCase): - mock_fqdn = "cloudinit.sources.util.get_fqdn_from_hosts" - with mock.patch("cloudinit.sources.util.get_hostname") as m_gethost: - with mock.patch(mock_fqdn) as m_fqdn: -- self.assertIsNone(datasource.get_hostname(metadata_only=True)) - self.assertIsNone( -- datasource.get_hostname(fqdn=True, metadata_only=True) -+ datasource.get_hostname(metadata_only=True).hostname -+ ) -+ self.assertIsNone( -+ datasource.get_hostname( -+ fqdn=True, metadata_only=True -+ ).hostname - ) - self.assertEqual([], m_gethost.call_args_list) - self.assertEqual([], m_fqdn.call_args_list) -@@ -335,10 +344,12 @@ class TestDataSource(CiTestCase): - with mock.patch(mock_fqdn) as m_fqdn: - m_gethost.return_value = "systemhostname.domain.com" - m_fqdn.return_value = "fqdnhostname.domain.com" -- self.assertEqual("fqdnhostname", datasource.get_hostname()) -+ self.assertEqual( -+ "fqdnhostname", datasource.get_hostname().hostname -+ ) - self.assertEqual( - "fqdnhostname.domain.com", -- datasource.get_hostname(fqdn=True), -+ datasource.get_hostname(fqdn=True).hostname, - ) - - def test_get_data_does_not_write_instance_data_on_failure(self): -diff --git a/tests/unittests/sources/test_scaleway.py b/tests/unittests/sources/test_scaleway.py -index d7e8b969..56735dd0 100644 ---- a/tests/unittests/sources/test_scaleway.py -+++ b/tests/unittests/sources/test_scaleway.py -@@ -236,7 +236,7 @@ class TestDataSourceScaleway(HttprettyTestCase): - ].sort(), - ) - self.assertEqual( -- self.datasource.get_hostname(), -+ self.datasource.get_hostname().hostname, - MetadataResponses.FAKE_METADATA["hostname"], - ) - self.assertEqual( -diff --git a/tests/unittests/sources/test_vmware.py b/tests/unittests/sources/test_vmware.py -index dd331349..753bb774 100644 ---- a/tests/unittests/sources/test_vmware.py -+++ b/tests/unittests/sources/test_vmware.py -@@ -368,7 +368,9 @@ class TestDataSourceVMwareGuestInfo_InvalidPlatform(FilesystemMockingTestCase): - - def assert_metadata(test_obj, ds, metadata): - test_obj.assertEqual(metadata.get("instance-id"), ds.get_instance_id()) -- test_obj.assertEqual(metadata.get("local-hostname"), ds.get_hostname()) -+ test_obj.assertEqual( -+ metadata.get("local-hostname"), ds.get_hostname().hostname -+ ) - - expected_public_keys = metadata.get("public_keys") - if not isinstance(expected_public_keys, list): -diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py -index 3765511b..528b7f36 100644 ---- a/tests/unittests/test_util.py -+++ b/tests/unittests/test_util.py -@@ -19,6 +19,7 @@ import pytest - import yaml - - from cloudinit import importer, subp, util -+from cloudinit.sources import DataSourceHostname - from tests.unittests import helpers - from tests.unittests.helpers import CiTestCase - -@@ -331,8 +332,8 @@ class FakeCloud(object): - myargs["metadata_only"] = metadata_only - self.calls.append(myargs) - if fqdn: -- return self.fqdn -- return self.hostname -+ return DataSourceHostname(self.fqdn, False) -+ return DataSourceHostname(self.hostname, False) - - - class TestUtil(CiTestCase): -@@ -420,7 +421,7 @@ class TestShellify(CiTestCase): - class TestGetHostnameFqdn(CiTestCase): - def test_get_hostname_fqdn_from_only_cfg_fqdn(self): - """When cfg only has the fqdn key, derive hostname and fqdn from it.""" -- hostname, fqdn = util.get_hostname_fqdn( -+ hostname, fqdn, _ = util.get_hostname_fqdn( - cfg={"fqdn": "myhost.domain.com"}, cloud=None - ) - self.assertEqual("myhost", hostname) -@@ -428,7 +429,7 @@ class TestGetHostnameFqdn(CiTestCase): - - def test_get_hostname_fqdn_from_cfg_fqdn_and_hostname(self): - """When cfg has both fqdn and hostname keys, return them.""" -- hostname, fqdn = util.get_hostname_fqdn( -+ hostname, fqdn, _ = util.get_hostname_fqdn( - cfg={"fqdn": "myhost.domain.com", "hostname": "other"}, cloud=None - ) - self.assertEqual("other", hostname) -@@ -436,7 +437,7 @@ class TestGetHostnameFqdn(CiTestCase): - - def test_get_hostname_fqdn_from_cfg_hostname_with_domain(self): - """When cfg has only hostname key which represents a fqdn, use that.""" -- hostname, fqdn = util.get_hostname_fqdn( -+ hostname, fqdn, _ = util.get_hostname_fqdn( - cfg={"hostname": "myhost.domain.com"}, cloud=None - ) - self.assertEqual("myhost", hostname) -@@ -445,7 +446,7 @@ class TestGetHostnameFqdn(CiTestCase): - def test_get_hostname_fqdn_from_cfg_hostname_without_domain(self): - """When cfg has a hostname without a '.' query cloud.get_hostname.""" - mycloud = FakeCloud("cloudhost", "cloudhost.mycloud.com") -- hostname, fqdn = util.get_hostname_fqdn( -+ hostname, fqdn, _ = util.get_hostname_fqdn( - cfg={"hostname": "myhost"}, cloud=mycloud - ) - self.assertEqual("myhost", hostname) -@@ -457,7 +458,7 @@ class TestGetHostnameFqdn(CiTestCase): - def test_get_hostname_fqdn_from_without_fqdn_or_hostname(self): - """When cfg has neither hostname nor fqdn cloud.get_hostname.""" - mycloud = FakeCloud("cloudhost", "cloudhost.mycloud.com") -- hostname, fqdn = util.get_hostname_fqdn(cfg={}, cloud=mycloud) -+ hostname, fqdn, _ = util.get_hostname_fqdn(cfg={}, cloud=mycloud) - self.assertEqual("cloudhost", hostname) - self.assertEqual("cloudhost.mycloud.com", fqdn) - self.assertEqual( -@@ -468,7 +469,7 @@ class TestGetHostnameFqdn(CiTestCase): - def test_get_hostname_fqdn_from_passes_metadata_only_to_cloud(self): - """Calls to cloud.get_hostname pass the metadata_only parameter.""" - mycloud = FakeCloud("cloudhost", "cloudhost.mycloud.com") -- _hn, _fqdn = util.get_hostname_fqdn( -+ _hn, _fqdn, _def_hostname = util.get_hostname_fqdn( - cfg={}, cloud=mycloud, metadata_only=True - ) - self.assertEqual( -diff --git a/tests/unittests/util.py b/tests/unittests/util.py -index 79a6e1d0..6fb39506 100644 ---- a/tests/unittests/util.py -+++ b/tests/unittests/util.py -@@ -1,5 +1,6 @@ - # This file is part of cloud-init. See LICENSE file for license information. - from cloudinit import cloud, distros, helpers -+from cloudinit.sources import DataSourceHostname - from cloudinit.sources.DataSourceNone import DataSourceNone - - -@@ -37,7 +38,7 @@ def abstract_to_concrete(abclass): - - class DataSourceTesting(DataSourceNone): - def get_hostname(self, fqdn=False, resolve_ip=False, metadata_only=False): -- return "hostname" -+ return DataSourceHostname("hostname", False) - - def persist_instance_data(self): - return True --- -2.31.1 - diff --git a/SOURCES/ci-cc_set_hostname-ignore-var-lib-cloud-data-set-hostna.patch b/SOURCES/ci-cc_set_hostname-ignore-var-lib-cloud-data-set-hostna.patch deleted file mode 100644 index c26c847..0000000 --- a/SOURCES/ci-cc_set_hostname-ignore-var-lib-cloud-data-set-hostna.patch +++ /dev/null @@ -1,77 +0,0 @@ -From d51546dee17c9abbb9d44fb33cf81be085a46dae Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Thu, 19 Jan 2023 09:40:10 +0100 -Subject: [PATCH 22/22] cc_set_hostname: ignore - /var/lib/cloud/data/set-hostname if it's empty (#1967) - -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2140893 - -commit 9c7502a801763520639c66125eb373123d1e4f44 -Author: Emanuele Giuseppe Esposito -Date: Wed Jan 18 17:55:16 2023 +0100 - - cc_set_hostname: ignore /var/lib/cloud/data/set-hostname if it's empty (#1967) - - If the file exists but is empty, do nothing. - Otherwise cloud-init will crash because it does not handle the empty file. - - RHBZ: 2140893 - - Signed-off-by: Emanuele Giuseppe Esposito - -Signed-off-by: Emanuele Giuseppe Esposito ---- - cloudinit/config/cc_set_hostname.py | 2 +- - tests/unittests/config/test_cc_set_hostname.py | 17 +++++++++++++++++ - 2 files changed, 18 insertions(+), 1 deletion(-) - -diff --git a/cloudinit/config/cc_set_hostname.py b/cloudinit/config/cc_set_hostname.py -index 2674fa20..7e3d5b74 100644 ---- a/cloudinit/config/cc_set_hostname.py -+++ b/cloudinit/config/cc_set_hostname.py -@@ -86,7 +86,7 @@ def handle(name, cfg, cloud, log, _args): - # distro._read_hostname implementation so we only validate one artifact. - prev_fn = os.path.join(cloud.get_cpath("data"), "set-hostname") - prev_hostname = {} -- if os.path.exists(prev_fn): -+ if os.path.exists(prev_fn) and os.stat(prev_fn).st_size > 0: - prev_hostname = util.load_json(util.load_file(prev_fn)) - hostname_changed = hostname != prev_hostname.get( - "hostname" -diff --git a/tests/unittests/config/test_cc_set_hostname.py b/tests/unittests/config/test_cc_set_hostname.py -index 3d1d86ee..2c92949f 100644 ---- a/tests/unittests/config/test_cc_set_hostname.py -+++ b/tests/unittests/config/test_cc_set_hostname.py -@@ -5,6 +5,7 @@ import os - import shutil - import tempfile - from io import BytesIO -+from pathlib import Path - from unittest import mock - - from configobj import ConfigObj -@@ -242,5 +243,21 @@ class TestHostname(t_help.FilesystemMockingTestCase): - str(ctx_mgr.exception), - ) - -+ def test_ignore_empty_previous_artifact_file(self): -+ cfg = { -+ "hostname": "blah", -+ "fqdn": "blah.blah.blah.yahoo.com", -+ } -+ distro = self._fetch_distro("debian") -+ paths = helpers.Paths({"cloud_dir": self.tmp}) -+ ds = None -+ cc = cloud.Cloud(ds, paths, {}, distro, None) -+ self.patchUtils(self.tmp) -+ prev_fn = Path(cc.get_cpath("data")) / "set-hostname" -+ prev_fn.touch() -+ cc_set_hostname.handle("cc_set_hostname", cfg, cc, LOG, []) -+ contents = util.load_file("/etc/hostname") -+ self.assertEqual("blah", contents.strip()) -+ - - # vi: ts=4 expandtab --- -2.39.1 - diff --git a/SOURCES/ci-cloud.cfg.tmpl-make-sure-centos-settings-are-identic.patch b/SOURCES/ci-cloud.cfg.tmpl-make-sure-centos-settings-are-identic.patch deleted file mode 100644 index df94668..0000000 --- a/SOURCES/ci-cloud.cfg.tmpl-make-sure-centos-settings-are-identic.patch +++ /dev/null @@ -1,139 +0,0 @@ -From dd5ae3081491a2a98bd74e1655b22c9354707630 Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Thu, 8 Sep 2022 17:46:45 +0200 -Subject: [PATCH] cloud.cfg.tmpl: make sure "centos" settings are identical to - "rhel" (#1639) - -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2115576 - -commit 7593243a1abe2ccaf4698579720999380a4da73b -Author: Emanuele Giuseppe Esposito -Date: Wed Sep 7 14:53:26 2022 +0200 - - cloud.cfg.tmpl: make sure "centos" settings are identical to "rhel" (#1639) - - We have a couple of bugs where centos does not have the default user as rhel. - This PR makes sure the configuration is exactly the same. - - Signed-off-by: Emanuele Giuseppe Esposito - - RHBZ: 2115565 - RHBZ: 2115576 - Conflicts: - config/cloud.cfg.tmpl: "openmandriva" distro added in the options - -Signed-off-by: Emanuele Giuseppe Esposito ---- - config/cloud.cfg.tmpl | 27 +++++++++++++------------ - tests/unittests/test_render_cloudcfg.py | 1 + - 2 files changed, 15 insertions(+), 13 deletions(-) - -diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl -index 80ab4f96..08b6efbc 100644 ---- a/config/cloud.cfg.tmpl -+++ b/config/cloud.cfg.tmpl -@@ -2,6 +2,7 @@ - # The top level settings are used as module - # and system configuration. - {% set is_bsd = variant in ["dragonfly", "freebsd", "netbsd", "openbsd"] %} -+{% set is_rhel = variant in ["rhel", "centos"] %} - {% if is_bsd %} - syslog_fix_perms: root:wheel - {% elif variant in ["suse"] %} -@@ -32,9 +33,9 @@ disable_root: false - disable_root: true - {% endif %} - --{% if variant in ["almalinux", "alpine", "amazon", "centos", "cloudlinux", "eurolinux", -- "fedora", "miraclelinux", "openEuler", "rhel", "rocky", "virtuozzo"] %} --{% if variant == "rhel" %} -+{% if variant in ["almalinux", "alpine", "amazon", "cloudlinux", "eurolinux", -+ "fedora", "miraclelinux", "openEuler", "openmandriva", "rocky", "virtuozzo"] or is_rhel %} -+{% if is_rhel %} - mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service,_netdev', '0', '2'] - {% else %} - mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2'] -@@ -70,7 +71,7 @@ network: - config: disabled - {% endif %} - --{% if variant == "rhel" %} -+{% if is_rhel %} - # Default redhat settings: - ssh_deletekeys: true - ssh_genkeytypes: ['rsa', 'ecdsa', 'ed25519'] -@@ -119,16 +120,16 @@ cloud_config_modules: - {% endif %} - {% if variant not in ["photon"] %} - - ssh-import-id --{% if variant not in ["rhel"] %} -+{% if not is_rhel %} - - keyboard - {% endif %} - - locale - {% endif %} - - set-passwords --{% if variant in ["rhel"] %} -+{% if is_rhel %} - - rh_subscription - {% endif %} --{% if variant in ["rhel", "fedora", "photon"] %} -+{% if variant in ["fedora", "openmandriva", "photon"] or is_rhel %} - {% if variant not in ["photon"] %} - - spacewalk - {% endif %} -@@ -193,9 +194,9 @@ cloud_final_modules: - # (not accessible to handlers/transforms) - system_info: - # This will affect which distro class gets used --{% if variant in ["almalinux", "alpine", "amazon", "arch", "centos", "cloudlinux", "debian", -+{% if variant in ["almalinux", "alpine", "amazon", "arch", "cloudlinux", "debian", - "eurolinux", "fedora", "freebsd", "gentoo", "netbsd", "miraclelinux", "openbsd", "openEuler", -- "photon", "rhel", "rocky", "suse", "ubuntu", "virtuozzo"] %} -+ "openmandriva", "photon", "rocky", "suse", "ubuntu", "virtuozzo"] or is_rhel %} - distro: {{ variant }} - {% elif variant in ["dragonfly"] %} - distro: dragonflybsd -@@ -248,15 +249,15 @@ system_info: - primary: http://ports.ubuntu.com/ubuntu-ports - security: http://ports.ubuntu.com/ubuntu-ports - ssh_svcname: ssh --{% elif variant in ["almalinux", "alpine", "amazon", "arch", "centos", "cloudlinux", "eurolinux", -- "fedora", "gentoo", "miraclelinux", "openEuler", "rhel", "rocky", "suse", "virtuozzo"] %} -+{% elif variant in ["almalinux", "alpine", "amazon", "arch", "cloudlinux", "eurolinux", -+ "fedora", "gentoo", "miraclelinux", "openEuler", "openmandriva", "rocky", "suse", "virtuozzo"] or is_rhel %} - # Default user name + that default users groups (if added/used) - default_user: - {% if variant == "amazon" %} - name: ec2-user - lock_passwd: True - gecos: EC2 Default User --{% elif variant == "rhel" %} -+{% elif is_rhel %} - name: cloud-user - lock_passwd: true - gecos: Cloud User -@@ -275,7 +276,7 @@ system_info: - groups: [adm, sudo] - {% elif variant == "arch" %} - groups: [wheel, users] --{% elif variant == "rhel" %} -+{% elif is_rhel %} - groups: [adm, systemd-journal] - {% else %} - groups: [wheel, adm, systemd-journal] -diff --git a/tests/unittests/test_render_cloudcfg.py b/tests/unittests/test_render_cloudcfg.py -index 9f95d448..1a6e2715 100644 ---- a/tests/unittests/test_render_cloudcfg.py -+++ b/tests/unittests/test_render_cloudcfg.py -@@ -69,6 +69,7 @@ class TestRenderCloudCfg: - "amazon": "ec2-user", - "debian": "ubuntu", - "rhel": "cloud-user", -+ "centos": "cloud-user", - "unknown": "ubuntu", - } - default_user = system_cfg["system_info"]["default_user"]["name"] --- -2.37.3 - diff --git a/SOURCES/ci-setup.py-adjust-udev-rules-default-path-1513.patch b/SOURCES/ci-setup.py-adjust-udev-rules-default-path-1513.patch deleted file mode 100644 index c46af8d..0000000 --- a/SOURCES/ci-setup.py-adjust-udev-rules-default-path-1513.patch +++ /dev/null @@ -1,57 +0,0 @@ -From f771d841dbdef8fbb1c1a3d1b8d51ff101354502 Mon Sep 17 00:00:00 2001 -From: Emanuele Giuseppe Esposito -Date: Fri, 17 Jun 2022 09:41:23 +0200 -Subject: [PATCH 3/3] setup.py: adjust udev/rules default path (#1513) - -RH-Author: Emanuele Giuseppe Esposito -RH-MergeRequest: 30: setup.py: adjust udev/rules default path (#1513) -RH-Commit: [2/2] b71362acefa15587b2c72e8981708065d2fcfa07 (eesposit/cloud-init-centos-) -RH-Bugzilla: 2096270 -RH-Acked-by: Mohamed Gamal Morsy -RH-Acked-by: Vitaly Kuznetsov - -commit 70715125f3af118ae242770e61064c24f41e9a02 -Author: Emanuele Giuseppe Esposito -Date: Thu Jun 16 20:39:42 2022 +0200 - - setup.py: adjust udev/rules default path (#1513) - - RHEL must put cloudinit .rules files in /usr/lib/udev/rules.d - This place is a rhel standard and since it is used by all packages - cannot be modified. - - Signed-off-by: Emanuele Giuseppe Esposito - -Signed-off-by: Emanuele Giuseppe Esposito ---- - setup.py | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/setup.py b/setup.py -index a9132d2c..fdf27cd7 100755 ---- a/setup.py -+++ b/setup.py -@@ -302,6 +302,11 @@ data_files = [ - ), - ] - if not platform.system().endswith("BSD"): -+ -+ RULES_PATH = LIB -+ if os.path.isfile("/etc/redhat-release"): -+ RULES_PATH = "/usr/lib" -+ - data_files.extend( - [ - ( -@@ -309,7 +314,7 @@ if not platform.system().endswith("BSD"): - ["tools/hook-network-manager"], - ), - (ETC + "/dhcp/dhclient-exit-hooks.d/", ["tools/hook-dhclient"]), -- (LIB + "/udev/rules.d", [f for f in glob("udev/*.rules")]), -+ (RULES_PATH + "/udev/rules.d", [f for f in glob("udev/*.rules")]), - ( - ETC + "/systemd/system/sshd-keygen@.service.d/", - ["systemd/disable-sshd-keygen-if-cloud-init-active.conf"], --- -2.35.1 - diff --git a/SPECS/cloud-init.spec b/SPECS/cloud-init.spec index 3078090..1a9c25d 100644 --- a/SPECS/cloud-init.spec +++ b/SPECS/cloud-init.spec @@ -1,61 +1,43 @@ Name: cloud-init -Version: 22.1 -Release: 9%{?dist} +Version: 23.1.1 +Release: 11%{?dist} Summary: Cloud instance init scripts License: ASL 2.0 or GPLv3 URL: http://launchpad.net/cloud-init -Source0: https://launchpad.net/cloud-init/trunk/%{version}/+download/%{name}-%{version}.tar.gz +Source0: https://github.com/canonical/cloud-init/archive/refs/tags/%{version}.tar.gz Source1: cloud-init-tmpfiles.conf -Patch0001: 0001-Add-initial-redhat-changes.patch -Patch0002: 0002-Do-not-write-NM_CONTROLLED-no-in-generated-interface.patch -Patch0003: 0003-Adding-_netdev-to-the-default-mount-configuration.patch -Patch0004: 0004-Setting-highest-autoconnect-priority-for-network-scr.patch -Patch0005: 0005-limit-permissions-on-def_log_file.patch -Patch0006: 0006-rhel-cloud.cfg-remove-ssh_genkeytypes-in-settings.py.patch -# For bz#2056964 - [RHEL-9]Rebase cloud-init from Fedora so it can configure networking using NM keyfiles -Patch7: ci-Add-native-NetworkManager-support-1224.patch -# For bz#2056964 - [RHEL-9]Rebase cloud-init from Fedora so it can configure networking using NM keyfiles -Patch8: ci-Use-Network-Manager-and-Netplan-as-default-renderers.patch -# For bz#2056964 - [RHEL-9]Rebase cloud-init from Fedora so it can configure networking using NM keyfiles -Patch9: ci-Revert-Setting-highest-autoconnect-priority-for-netw.patch -# For bz#2088448 - Align cloud.cfg file and systemd with cloud-init upstream .tmpl files -Patch10: ci-Align-rhel-custom-files-with-upstream-1431.patch -# For bz#2088448 - Align cloud.cfg file and systemd with cloud-init upstream .tmpl files -Patch11: ci-Remove-rhel-specific-files.patch -# For bz#2091640 - [cloud][init] Add support for reading tags from instance metadata -Patch12: ci-Support-EC2-tags-in-instance-metadata-1309.patch -# For bz#1980403 - [RHV] RHEL 9 VM with cloud-init without hostname set doesn't result in the FQDN as hostname -Patch13: ci-cc_set_hostname-do-not-write-localhost-when-no-hostn.patch -# For bz#2061604 - cloud-config will change /etc/locale.conf back to en_US.UTF-8 on rhel-guest-image-9.0 -Patch14: ci-Honor-system-locale-for-RHEL-1355.patch -# For bz#2096270 - Adjust udev/rules default path[rhel-9] -Patch15: ci-setup.py-adjust-udev-rules-default-path-1513.patch -# For bz#2107463 - [RHEL-9.1] Cannot run sysconfig when changing the priority of network renderers -# For bz#2104389 - [RHEL-9.1]Failed to config static IP and IPv6 according to VMware Customization Config File -# For bz#2117532 - [RHEL9.1] Revert patch of configuring networking by NM keyfiles -# For bz#2098501 - [RHEL-9.1] IPv6 not workable when cloud-init configure network using NM keyfiles -Patch16: ci-Revert-Add-native-NetworkManager-support-1224.patch -# For bz#2107463 - [RHEL-9.1] Cannot run sysconfig when changing the priority of network renderers -# For bz#2104389 - [RHEL-9.1]Failed to config static IP and IPv6 according to VMware Customization Config File -# For bz#2117532 - [RHEL9.1] Revert patch of configuring networking by NM keyfiles -# For bz#2098501 - [RHEL-9.1] IPv6 not workable when cloud-init configure network using NM keyfiles -Patch17: ci-Revert-Use-Network-Manager-and-Netplan-as-default-re.patch -# For bz#2107463 - [RHEL-9.1] Cannot run sysconfig when changing the priority of network renderers -# For bz#2104389 - [RHEL-9.1]Failed to config static IP and IPv6 according to VMware Customization Config File -# For bz#2117532 - [RHEL9.1] Revert patch of configuring networking by NM keyfiles -# For bz#2098501 - [RHEL-9.1] IPv6 not workable when cloud-init configure network using NM keyfiles -Patch18: ci-Revert-Revert-Setting-highest-autoconnect-priority-f.patch -# For bz#2115565 - cloud-init configures user "centos" or "rhel" instead of "cloud-user" with cloud-init-22.1 -Patch19: ci-cloud.cfg.tmpl-make-sure-centos-settings-are-identic.patch -# For bz#2152100 - [RHEL-9] Ensure network ready before cloud-init service runs on RHEL -Patch20: ci-Ensure-network-ready-before-cloud-init-service-runs-.patch -# For bz#2140893 - systemd[1]: Failed to start Initial cloud-init job after reboot system via sysrq 'b' -Patch21: ci-cc_set_hostname-ignore-var-lib-cloud-data-set-hostna.patch -# For bz#2166245 - Add support for resizing encrypted root volume -Patch22: ci-Allow-growpart-to-resize-encrypted-partitions-1316.patch - # Source-git patches +Patch1: 0001-Add-initial-redhat-changes.patch +Patch2: 0002-Do-not-write-NM_CONTROLLED-no-in-generated-interface.patch +Patch3: 0003-Setting-highest-autoconnect-priority-for-network-scr.patch +Patch4: 0004-limit-permissions-on-def_log_file.patch +Patch5: 0005-Manual-revert-Use-Network-Manager-and-Netplan-as-def.patch +Patch6: 0006-Revert-Add-native-NetworkManager-support-1224.patch +Patch7: 0007-rhel-make-sure-previous-hostname-file-ends-with-a-ne.patch +Patch8: 0008-Don-t-change-permissions-of-netrules-target-2076.patch +Patch9: 0009-Make-user-vendor-data-sensitive-and-remove-log-permi.patch +Patch10: 0010-Do-not-generate-dsa-and-ed25519-key-types-when-crypt.patch +Patch11: 0011-Revert-Manual-revert-Use-Network-Manager-and-Netplan.patch +Patch12: 0012-Revert-Revert-Add-native-NetworkManager-support-1224.patch +Patch13: 0013-net-sysconfig-do-not-use-the-highest-autoconnect-pri.patch +Patch14: 0014-net-sysconfig-cosmetic-fix-tox-formatting.patch +Patch15: 0015-nm-generate-ipv6-stateful-dhcp-config-at-par-with-sy.patch +Patch16: 0016-network_manager-add-a-method-for-ipv6-static-IP-conf.patch +Patch17: 0017-net-sysconfig-enable-sysconfig-renderer-if-network-m.patch +Patch18: 0018-network-manager-Set-higher-autoconnect-priority-for-.patch +Patch19: 0019-Set-default-renderer-as-sysconfig-for-c9s-RHEL-9.patch +Patch20: 0020-Revert-Set-default-renderer-as-sysconfig-for-c9s-RHE.patch +Patch21: 0021-Set-default-renderer-as-sysconfig-for-centos-rhel-41.patch +Patch22: 0022-test-fixes-update-tests-to-reflect-AUTOCONNECT_PRIOR.patch +Patch23: 0023-test-fixes-remove-NM_CONTROLLED-no-from-tests.patch +Patch24: 0024-Revert-limit-permissions-on-def_log_file.patch +Patch25: 0025-test-fixes-changes-to-apply-RHEL-specific-config-set.patch +Patch26: 0026-Enable-SUSE-based-distros-for-ca-handling-2036.patch +Patch27: 0027-Handle-non-existent-ca-cert-config-situation-2073.patch +Patch28: 0028-logging-keep-current-file-mode-of-log-file-if-its-st.patch +Patch29: 0029-DS-VMware-modify-a-few-log-level-4284.patch +Patch30: 0030-NM-renderer-set-default-IPv6-addr-gen-mode-for-all-i.patch BuildArch: noarch @@ -175,7 +157,27 @@ if [ $1 -eq 1 ] ; then /bin/systemctl enable cloud-init-local.service >/dev/null 2>&1 || : /bin/systemctl enable cloud-init.target >/dev/null 2>&1 || : elif [ $1 -eq 2 ]; then - # Upgrade. If the upgrade is from a version older than 0.7.9-8, + # Upgrade + # RHBZ 2210012 - check for null ssh_genkeytypes value in cloud.cfg that + # breaks ssh connectivity after upgrade to a newer version of cloud-init. + if [ -f %{_sysconfdir}/cloud/cloud.cfg.rpmnew ] && grep -q '^\s*ssh_genkeytypes:\s*~\s*$' %{_sysconfdir}/cloud/cloud.cfg ; then + echo "***********************************************" + echo "*** WARNING!!!! ***" + echo "" + echo "ssh_genkeytypes set to null in /etc/cloud/cloud.cfg!" + echo "SSH access might be broken after reboot. Please check the following KCS" + echo "for more detailed information:" + echo "" + echo "https://access.redhat.com/solutions/6988034" + echo "" + echo "Please reconcile the differences between /etc/cloud/cloud.cfg and " + echo "/etc/cloud/cloud.cfg.rpmnew and update ssh_genkeytypes configuration in " + echo "/etc/cloud/cloud.cfg to a list of keytype values, something like:" + echo "ssh_genkeytypes: ['rsa', 'ecdsa', 'ed25519']" + echo "" + echo "************************************************" + fi + # If the upgrade is from a version older than 0.7.9-8, # there will be stale systemd config /bin/systemctl is-enabled cloud-config.service >/dev/null 2>&1 && /bin/systemctl reenable cloud-config.service >/dev/null 2>&1 || : @@ -207,6 +209,17 @@ fi %postun %systemd_postun cloud-config.service cloud-config.target cloud-final.service cloud-init.service cloud-init.target cloud-init-local.service +if [ -f /etc/ssh/sshd_config.d/50-cloud-init.conf ] ; then + echo "/etc/ssh/sshd_config.d/50-cloud-init.conf not removed" +fi + +if [ -f /etc/NetworkManager/conf.d/99-cloud-init.conf ] ; then + echo "/etc/NetworkManager/conf.d/99-cloud-init.conf not removed" +fi + +if [ -f /etc/NetworkManager/conf.d/30-cloud-init-ip6-addr-gen-mode.conf ] ; then + echo "/etc/NetworkManager/conf.d/30-cloud-init-ip6-addr-gen-mode.conf not removed" +fi %files %license LICENSE @@ -214,6 +227,7 @@ fi %dir %{_sysconfdir}/cloud/cloud.cfg.d %config(noreplace) %{_sysconfdir}/cloud/cloud.cfg.d/*.cfg %doc %{_sysconfdir}/cloud/cloud.cfg.d/README +%doc %{_sysconfdir}/cloud/clean.d/README %dir %{_sysconfdir}/cloud/templates %config(noreplace) %{_sysconfdir}/cloud/templates/* %{_unitdir}/cloud-config.service @@ -244,6 +258,64 @@ fi %config(noreplace) %{_sysconfdir}/rsyslog.d/21-cloudinit.conf %changelog +* Thu Aug 17 2023 Miroslav Rezanina - 23.1.1-11 +- Resolves: bz#2232296 + +* Tue Aug 15 2023 Miroslav Rezanina <6499514-mrezanin@users.noreply.gitlab.com> - 23.1.1-10 +- Resolves: bz#2229660 bz#2229952 + +* Fri Aug 04 2023 Camilla Conte - 23.1.1-9 +- 0030-NM-renderer-set-default-IPv6-addr-gen-mode-for-all-i.patch [bz#2188388] +- Resolves: bz#2188388 + +* Wed Jul 26 2023 Camilla Conte - 23.1.1-8 +- 0022-test-fixes-update-tests-to-reflect-AUTOCONNECT_PRIOR.patch [bz#2217865] +- 0023-test-fixes-remove-NM_CONTROLLED-no-from-tests.patch [bz#2217865] +- 0024-Revert-limit-permissions-on-def_log_file.patch [bz#2217865] +- 0025-test-fixes-changes-to-apply-RHEL-specific-config-set.patch [bz#2217865] +- 0026-Enable-SUSE-based-distros-for-ca-handling-2036.patch [bz#2217865] +- 0027-Handle-non-existent-ca-cert-config-situation-2073.patch [bz#2217865] +- 0028-logging-keep-current-file-mode-of-log-file-if-its-st.patch [bz#2222498] +- 0029-DS-VMware-modify-a-few-log-level-4284.patch [bz#2225374] +- Resolves: bz#2217865 bz#2222498 bz#2225374 + +* Mon Jun 19 2023 Miroslav Rezanina - 23.1.1-7 +- 0020-Revert-Set-default-renderer-as-sysconfig-for-c9s-RHE.patch +- 0021-Set-default-renderer-as-sysconfig-for-centos-rhel-41.patch [bz#2209349] +- Resolves: bz#2209349 + +* Tue Jun 06 2023 Camilla Conte - 23.1.1-6 +- 0011-Revert-Manual-revert-Use-Network-Manager-and-Netplan.patch +- 0012-Revert-Revert-Add-native-NetworkManager-support-1224.patch +- 0013-net-sysconfig-do-not-use-the-highest-autoconnect-pri.patch +- 0014-net-sysconfig-cosmetic-fix-tox-formatting.patch +- 0015-nm-generate-ipv6-stateful-dhcp-config-at-par-with-sy.patch [bz#2207716] +- 0016-network_manager-add-a-method-for-ipv6-static-IP-conf.patch [bz#2196284] +- 0017-net-sysconfig-enable-sysconfig-renderer-if-network-m.patch [bz#2194050] +- 0018-network-manager-Set-higher-autoconnect-priority-for-.patch [bz#2196231] +- 0019-Set-default-renderer-as-sysconfig-for-c9s-RHEL-9.patch [bz#2209349] +- Resolves: bz#2118235 bz#2194050 bz#2196231 bz#2196284 bz#2207716 bz#2209349 + +* Tue May 16 2023 Camilla Conte - 23.1.1-5 +- 0010-Do-not-generate-dsa-and-ed25519-key-types-when-crypt.patch [bz#2187164] +- Resolves: bz#2187164 + +* Fri May 05 2023 Camilla Conte - 23.1.1-4 +- 0009-Make-user-vendor-data-sensitive-and-remove-log-permi.patch [bz#2190083] +- Resolves: bz#2190083 + +* Thu Apr 27 2023 Camilla Conte - 23.1.1-3 +- 0008-Don-t-change-permissions-of-netrules-target-2076.patch [bz#2182948] +- Resolves: bz#2182948 + +* Tue Apr 18 2023 Camilla Conte - 23.1.1-2 +- 0007-rhel-make-sure-previous-hostname-file-ends-with-a-ne.patch [bz#2184608] +- Resolves: bz#2184608 + +* Thu Mar 30 2023 Camilla Conte - 23.1.1-1 +- Rebase to 23.1.1 [bz#2172811] +- Resolves: bz#2172811 + * Wed Feb 08 2023 Camilla Conte - 22.1-9 - ci-Allow-growpart-to-resize-encrypted-partitions-1316.patch [bz#2166245] - Resolves: bz#2166245