import cloud-init-19.4-11.el8_3.3

This commit is contained in:
CentOS Sources 2021-04-06 09:33:04 -04:00 committed by Andrew Lukoshko
commit 836d75c274
34 changed files with 6535 additions and 0 deletions

1
.cloud-init.metadata Normal file
View File

@ -0,0 +1 @@
5f4de38850f9691dc9789bd4db4be512c9717d7b SOURCES/cloud-init-19.4.tar.gz

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
SOURCES/cloud-init-19.4.tar.gz

View File

@ -0,0 +1,533 @@
From 4114343d0cd2fc3e5566eed27272480e003c89cc Mon Sep 17 00:00:00 2001
From: Miroslav Rezanina <mrezanin@redhat.com>
Date: Thu, 31 May 2018 16:45:23 +0200
Subject: Add initial redhat setup
Rebase notes (18.5):
- added bash_completition file
- added cloud-id file
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
---
.gitignore | 1 +
cloudinit/config/cc_chef.py | 6 +-
cloudinit/settings.py | 7 +-
redhat/.gitignore | 1 +
redhat/Makefile | 71 ++++++
redhat/Makefile.common | 37 +++
redhat/cloud-init-tmpfiles.conf | 1 +
redhat/cloud-init.spec.template | 438 ++++++++++++++++++++++++++++++++++
redhat/gating.yaml | 9 +
redhat/rpmbuild/BUILD/.gitignore | 3 +
redhat/rpmbuild/RPMS/.gitignore | 3 +
redhat/rpmbuild/SOURCES/.gitignore | 3 +
redhat/rpmbuild/SPECS/.gitignore | 3 +
redhat/rpmbuild/SRPMS/.gitignore | 3 +
redhat/scripts/frh.py | 27 +++
redhat/scripts/git-backport-diff | 327 +++++++++++++++++++++++++
redhat/scripts/git-compile-check | 215 +++++++++++++++++
redhat/scripts/process-patches.sh | 73 ++++++
redhat/scripts/tarball_checksum.sh | 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 | 19 ++
rhel/systemd/cloud-init-local.service | 31 +++
rhel/systemd/cloud-init.service | 25 ++
rhel/systemd/cloud-init.target | 7 +
setup.py | 70 +-----
tools/read-version | 28 +--
30 files changed, 1417 insertions(+), 98 deletions(-)
create mode 100644 redhat/.gitignore
create mode 100644 redhat/Makefile
create mode 100644 redhat/Makefile.common
create mode 100644 redhat/cloud-init-tmpfiles.conf
create mode 100644 redhat/cloud-init.spec.template
create mode 100644 redhat/gating.yaml
create mode 100644 redhat/rpmbuild/BUILD/.gitignore
create mode 100644 redhat/rpmbuild/RPMS/.gitignore
create mode 100644 redhat/rpmbuild/SOURCES/.gitignore
create mode 100644 redhat/rpmbuild/SPECS/.gitignore
create mode 100644 redhat/rpmbuild/SRPMS/.gitignore
create mode 100755 redhat/scripts/frh.py
create mode 100755 redhat/scripts/git-backport-diff
create mode 100755 redhat/scripts/git-compile-check
create mode 100755 redhat/scripts/process-patches.sh
create mode 100755 redhat/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
diff --git a/cloudinit/config/cc_chef.py b/cloudinit/config/cc_chef.py
index 0ad6b7f..e4408a4 100644
--- a/cloudinit/config/cc_chef.py
+++ b/cloudinit/config/cc_chef.py
@@ -33,7 +33,7 @@ file).
chef:
directories: (defaulting to /etc/chef, /var/log/chef, /var/lib/chef,
- /var/cache/chef, /var/backups/chef, /var/run/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
@@ -89,7 +89,7 @@ CHEF_DIRS = tuple([
'/var/lib/chef',
'/var/cache/chef',
'/var/backups/chef',
- '/var/run/chef',
+ '/run/chef',
])
REQUIRED_CHEF_DIRS = tuple([
'/etc/chef',
@@ -113,7 +113,7 @@ CHEF_RB_TPL_DEFAULTS = {
'json_attribs': CHEF_FB_PATH,
'file_cache_path': "/var/cache/chef",
'file_backup_path': "/var/backups/chef",
- 'pid_file': "/var/run/chef/client.pid",
+ 'pid_file': "/run/chef/client.pid",
'show_time': True,
'encrypted_data_bag_secret': None,
}
diff --git a/cloudinit/settings.py b/cloudinit/settings.py
index ca4ffa8..3a04a58 100644
--- a/cloudinit/settings.py
+++ b/cloudinit/settings.py
@@ -46,13 +46,16 @@ CFG_BUILTIN = {
],
'def_log_file': '/var/log/cloud-init.log',
'log_cfgs': [],
- 'syslog_fix_perms': ['syslog:adm', 'root:adm', 'root:wheel', 'root:root'],
+ '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/',
},
- 'distro': 'ubuntu',
+ 'distro': 'rhel',
'network': {'renderers': None},
},
'vendor_data': {'enabled': True, 'prefix': []},
diff --git a/rhel/README.rhel b/rhel/README.rhel
new file mode 100644
index 0000000..aa29630
--- /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 0000000..0c6d2a3
--- /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 0000000..82e8bf6
--- /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: 0
+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 0000000..f3dcd4b
--- /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 0000000..ae9b7d0
--- /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 0000000..739b7e3
--- /dev/null
+++ b/rhel/systemd/cloud-final.service
@@ -0,0 +1,19 @@
+[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
+
+# 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 0000000..8f9f6c9
--- /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 0000000..d0023a0
--- /dev/null
+++ b/rhel/systemd/cloud-init.service
@@ -0,0 +1,25 @@
+[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
+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 0000000..083c3b6
--- /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 01a67b9..b2ac9bb 100755
--- a/setup.py
+++ b/setup.py
@@ -139,14 +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/*.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 = {
@@ -155,9 +147,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()])
@@ -208,47 +197,6 @@ class MyEggInfo(egg_info):
return ret
-# TODO: Is there a better way to do this??
-class InitsysInstallData(install):
- init_system = None
- user_options = install.user_options + [
- # This will magically show up in member variable 'init_sys'
- ('init-system=', None,
- ('init system(s) to configure (%s) [default: None]' %
- (", ".join(INITSYS_TYPES)))),
- ]
-
- def initialize_options(self):
- install.initialize_options(self)
- self.init_system = ""
-
- def finalize_options(self):
- install.finalize_options(self)
-
- if self.init_system and isinstance(self.init_system, str):
- self.init_system = self.init_system.split(",")
-
- if len(self.init_system) == 0:
- self.init_system = ['systemd']
-
- bad = [f for f in self.init_system if f not in INITSYS_TYPES]
- if len(bad) != 0:
- raise DistutilsArgError(
- "Invalid --init-system: %s" % (','.join(bad)))
-
- for system in self.init_system:
- # add data files for anything that starts with '<system>.'
- datakeys = [k for k in INITSYS_ROOTS
- if k.partition(".")[0] == system]
- for k in datakeys:
- if not INITSYS_FILES[k]:
- continue
- self.distribution.data_files.append(
- (INITSYS_ROOTS[k], INITSYS_FILES[k]))
- # Force that command to reinitalize (with new file list)
- self.distribution.reinitialize_command('install_data', True)
-
-
if not in_virtualenv():
USR = "/" + USR
ETC = "/" + ETC
@@ -258,14 +206,11 @@ if not in_virtualenv():
INITSYS_ROOTS[k] = "/" + INITSYS_ROOTS[k]
data_files = [
- (ETC + '/cloud', [render_tmpl("config/cloud.cfg.tmpl")]),
+ (ETC + '/bash_completion.d', ['bash_completion/cloud-init']),
(ETC + '/cloud/cloud.cfg.d', glob('config/cloud.cfg.d/*')),
(ETC + '/cloud/templates', glob('templates/*')),
- (USR_LIB_EXEC + '/cloud-init', ['tools/ds-identify',
- 'tools/uncloud-init',
+ (USR_LIB_EXEC + '/cloud-init', ['tools/uncloud-init',
'tools/write-ssh-key-fingerprints']),
- (USR + '/share/bash-completion/completions',
- ['bash_completion/cloud-init']),
(USR + '/share/doc/cloud-init', [f for f in glob('doc/*') if is_f(f)]),
(USR + '/share/doc/cloud-init/examples',
[f for f in glob('doc/examples/*') if is_f(f)]),
@@ -276,15 +221,8 @@ if os.uname()[0] != 'FreeBSD':
data_files.extend([
(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')])
])
-# Use a subclass for install that handles
-# adding on the right init system configuration files
-cmdclass = {
- 'install': InitsysInstallData,
- 'egg_info': MyEggInfo,
-}
requirements = read_requires()
@@ -299,8 +237,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 6dca659..d43cc8f 100755
--- a/tools/read-version
+++ b/tools/read-version
@@ -65,32 +65,8 @@ output_json = '--json' in sys.argv
src_version = ci_version.version_string()
version_long = None
-if is_gitdir(_tdir) and which("git"):
- 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
--
1.8.3.1

View File

@ -0,0 +1,271 @@
From aa7ae9da7e10a5bcf190f8df3072e3864b2d8fb3 Mon Sep 17 00:00:00 2001
From: Miroslav Rezanina <mrezanin@redhat.com>
Date: Thu, 31 May 2018 19:37:55 +0200
Subject: Do not write NM_CONTROLLED=no in generated interface config files
X-downstream-only: true
Signed-off-by: Ryan McCabe <rmccabe@redhat.com>
---
cloudinit/net/sysconfig.py | 1 -
tests/unittests/test_net.py | 30 ------------------------------
2 files changed, 31 deletions(-)
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index 310cdf0..8bd7e88 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -272,7 +272,6 @@ class Renderer(renderer.Renderer):
iface_defaults = tuple([
('ONBOOT', True),
('USERCTL', False),
- ('NM_CONTROLLED', False),
('BOOTPROTO', 'none'),
('STARTMODE', 'auto'),
])
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index 01119e0..a931a3e 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -530,7 +530,6 @@ GATEWAY=172.19.3.254
HWADDR=fa:16:3e:ed:9a:59
IPADDR=172.19.1.34
NETMASK=255.255.252.0
-NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -636,7 +635,6 @@ IPADDR=172.19.1.34
IPADDR1=10.0.0.10
NETMASK=255.255.252.0
NETMASK1=255.255.255.0
-NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -772,7 +770,6 @@ IPV6ADDR_SECONDARIES="2001:DB9::10/64 2001:DB10::10/64"
IPV6INIT=yes
IPV6_DEFAULTGW=2001:DB8::1
NETMASK=255.255.252.0
-NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -889,7 +886,6 @@ NETWORK_CONFIGS = {
BOOTPROTO=none
DEVICE=eth1
HWADDR=cf:d6:af:48:e8:80
- NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -907,7 +903,6 @@ NETWORK_CONFIGS = {
IPADDR=192.168.21.3
NETMASK=255.255.255.0
METRIC=10000
- NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -1022,7 +1017,6 @@ NETWORK_CONFIGS = {
IPV6ADDR=2001:1::1/64
IPV6INIT=yes
NETMASK=255.255.255.0
- NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -1491,7 +1485,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
- NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Bond
@@ -1500,7 +1493,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
- NM_CONTROLLED=no
ONBOOT=yes
PHYSDEV=bond0
STARTMODE=auto
@@ -1519,7 +1511,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
- NM_CONTROLLED=no
ONBOOT=yes
PRIO=22
STARTMODE=auto
@@ -1530,7 +1521,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
- NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -1548,7 +1538,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
- NM_CONTROLLED=no
ONBOOT=yes
PHYSDEV=eth0
STARTMODE=auto
@@ -1560,7 +1549,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
- NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
SLAVE=yes
@@ -1571,7 +1559,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
- NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
SLAVE=yes
@@ -1582,7 +1569,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
- NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -1592,7 +1578,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
- NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -1602,7 +1587,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
- NM_CONTROLLED=no
ONBOOT=no
STARTMODE=manual
TYPE=Ethernet
@@ -2088,7 +2072,6 @@ iface bond0 inet6 static
MTU=9000
NETMASK=255.255.255.0
NETMASK1=255.255.255.0
- NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Bond
@@ -2099,7 +2082,6 @@ iface bond0 inet6 static
DEVICE=bond0s0
HWADDR=aa:bb:cc:dd:e8:00
MASTER=bond0
- NM_CONTROLLED=no
ONBOOT=yes
SLAVE=yes
STARTMODE=auto
@@ -2122,7 +2104,6 @@ iface bond0 inet6 static
DEVICE=bond0s1
HWADDR=aa:bb:cc:dd:e8:01
MASTER=bond0
- NM_CONTROLLED=no
ONBOOT=yes
SLAVE=yes
STARTMODE=auto
@@ -2161,7 +2142,6 @@ iface bond0 inet6 static
BOOTPROTO=none
DEVICE=en0
HWADDR=aa:bb:cc:dd:e8:00
- NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -2180,7 +2160,6 @@ iface bond0 inet6 static
MTU=2222
NETMASK=255.255.255.0
NETMASK1=255.255.255.0
- NM_CONTROLLED=no
ONBOOT=yes
PHYSDEV=en0
STARTMODE=auto
@@ -2222,7 +2201,6 @@ iface bond0 inet6 static
DEVICE=br0
IPADDR=192.168.2.2
NETMASK=255.255.255.0
- NM_CONTROLLED=no
ONBOOT=yes
PRIO=22
STARTMODE=auto
@@ -2238,7 +2216,6 @@ iface bond0 inet6 static
IPADDR6=2001:1::100/96
IPV6ADDR=2001:1::100/96
IPV6INIT=yes
- NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -2252,7 +2229,6 @@ iface bond0 inet6 static
IPADDR6=2001:1::101/96
IPV6ADDR=2001:1::101/96
IPV6INIT=yes
- NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -2327,7 +2303,6 @@ iface bond0 inet6 static
HWADDR=52:54:00:12:34:00
IPADDR=192.168.1.2
NETMASK=255.255.255.0
- NM_CONTROLLED=no
ONBOOT=no
STARTMODE=manual
TYPE=Ethernet
@@ -2338,7 +2313,6 @@ iface bond0 inet6 static
DEVICE=eth1
HWADDR=52:54:00:12:34:aa
MTU=1480
- NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -2348,7 +2322,6 @@ iface bond0 inet6 static
BOOTPROTO=none
DEVICE=eth2
HWADDR=52:54:00:12:34:ff
- NM_CONTROLLED=no
ONBOOT=no
STARTMODE=manual
TYPE=Ethernet
@@ -2766,7 +2739,6 @@ class TestRhelSysConfigRendering(CiTestCase):
BOOTPROTO=dhcp
DEVICE=eth1000
HWADDR=07-1c-c6-75-a4-be
-NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -2888,7 +2860,6 @@ GATEWAY=10.0.2.2
HWADDR=52:54:00:12:34:00
IPADDR=10.0.2.15
NETMASK=255.255.255.0
-NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -2961,7 +2932,6 @@ USERCTL=no
#
BOOTPROTO=dhcp
DEVICE=eth0
-NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
--
1.8.3.1

View File

@ -0,0 +1,66 @@
From f15946568fe731dc9bf477f3f06c9c4e0f74f7c1 Mon Sep 17 00:00:00 2001
From: Lars Kellogg-Stedman <lars@redhat.com>
Date: Fri, 7 Apr 2017 18:50:54 -0400
Subject: 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.
LP: #1541196
Resolves: rhbz#1424612
X-approved-upstream: true
---
cloudinit/settings.py | 1 +
cloudinit/stages.py | 3 ++-
doc/examples/cloud-config.txt | 4 ++++
3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/cloudinit/settings.py b/cloudinit/settings.py
index 3a04a58..439eee0 100644
--- a/cloudinit/settings.py
+++ b/cloudinit/settings.py
@@ -45,6 +45,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,
diff --git a/cloudinit/stages.py b/cloudinit/stages.py
index 71f3a49..68b83af 100644
--- a/cloudinit/stages.py
+++ b/cloudinit/stages.py
@@ -149,8 +149,9 @@ class Init(object):
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:
- util.ensure_file(log_file)
+ util.ensure_file(log_file, mode=log_file_mode)
perms = self.cfg.get('syslog_fix_perms')
if not perms:
perms = {}
diff --git a/doc/examples/cloud-config.txt b/doc/examples/cloud-config.txt
index eb84dcf..0e82b83 100644
--- a/doc/examples/cloud-config.txt
+++ b/doc/examples/cloud-config.txt
@@ -413,10 +413,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.
#
+# '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
--
1.8.3.1

View File

@ -0,0 +1,34 @@
From e2b22710db558df261883eaf5dde866c69ba17dd Mon Sep 17 00:00:00 2001
From: Miroslav Rezanina <mrezanin@redhat.com>
Date: Thu, 31 May 2018 20:00:32 +0200
Subject: sysconfig: Don't write BOOTPROTO=dhcp for ipv6 dhcp
Don't write BOOTPROTO=dhcp for ipv6 dhcp, as BOOTPROTO applies
only to ipv4. Explicitly write IPV6_AUTOCONF=no for dhcp on ipv6.
X-downstream-only: yes
Resolves: rhbz#1519271
Signed-off-by: Ryan McCabe <rmccabe@redhat.com>
Merged patches (19.4):
- 6444df4 sysconfig: Don't disable IPV6_AUTOCONF
---
tests/unittests/test_net.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index a931a3e..1306a0f 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -1483,6 +1483,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true
BOOTPROTO=none
DEVICE=bond0
DHCPV6C=yes
+ IPV6_AUTOCONF=no
IPV6INIT=yes
MACADDR=aa:bb:cc:dd:ee:ff
ONBOOT=yes
--
1.8.3.1

View File

@ -0,0 +1,56 @@
From 9a09efb49c2d7cade1f0ac309293166c3c2d8d7b Mon Sep 17 00:00:00 2001
From: Vitaly Kuznetsov <vkuznets@redhat.com>
Date: Tue, 17 Apr 2018 13:07:54 +0200
Subject: DataSourceAzure.py: use hostnamectl to set hostname
RH-Author: Vitaly Kuznetsov <vkuznets@redhat.com>
Message-id: <20180417130754.12918-3-vkuznets@redhat.com>
Patchwork-id: 79659
O-Subject: [RHEL7.6/7.5.z cloud-init PATCH 2/2] DataSourceAzure.py: use hostnamectl to set hostname
Bugzilla: 1568717
RH-Acked-by: Eduardo Otubo <otubo@redhat.com>
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
RH-Acked-by: Cathy Avery <cavery@redhat.com>
The right way to set hostname in RHEL7 is:
$ hostnamectl set-hostname HOSTNAME
DataSourceAzure, however, uses:
$ hostname HOSTSNAME
instead and this causes problems. We can't simply change
'BUILTIN_DS_CONFIG' in DataSourceAzure.py as 'hostname' is being used
for both getting and setting the hostname.
Long term, this should be fixed in a different way. Cloud-init
has distro-specific hostname setting/getting (see
cloudinit/distros/rhel.py) and DataSourceAzure.py needs to be switched
to use these.
Resolves: rhbz#1434109
X-downstream-only: yes
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
cloudinit/sources/DataSourceAzure.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
index 24f448c..6fb889c 100755
--- a/cloudinit/sources/DataSourceAzure.py
+++ b/cloudinit/sources/DataSourceAzure.py
@@ -256,7 +256,7 @@ def get_hostname(hostname_command='hostname'):
def set_hostname(hostname, hostname_command='hostname'):
- util.subp([hostname_command, hostname])
+ util.subp(['hostnamectl', 'set-hostname', str(hostname)])
@azure_ds_telemetry_reporter
--
1.8.3.1

View File

@ -0,0 +1,65 @@
From 13ee71a3add0dd2e7c60fc672134e696bd7f6a77 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Wed, 20 Mar 2019 11:45:59 +0100
Subject: include 'NOZEROCONF=yes' in /etc/sysconfig/network
RH-Author: Eduardo Otubo <otubo@redhat.com>
Message-id: <20190320114559.23708-1-otubo@redhat.com>
Patchwork-id: 84937
O-Subject: [RHEL-7.7 cloud-init PATCH] include 'NOZEROCONF=yes' in /etc/sysconfig/network
Bugzilla: 1653131
RH-Acked-by: Cathy Avery <cavery@redhat.com>
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
The option NOZEROCONF=yes is not included by default in
/etc/sysconfig/network, which is required by Overcloud instances. The
patch also includes tests for the modifications.
X-downstream-only: yes
Resolves: rhbz#1653131
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
cloudinit/net/sysconfig.py | 11 ++++++++++-
tests/unittests/test_net.py | 1 -
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index 8bd7e88..810b283 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -754,7 +754,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))
- netcfg = [_make_header(), 'NETWORKING=yes']
+ netcfg = []
+ for line in util.load_file(sysconfig_path, quiet=True).split('\n'):
+ if 'cloud-init' in line:
+ break
+ if not line.startswith(('NETWORKING=',
+ 'IPV6_AUTOCONF=',
+ 'NETWORKING_IPV6=')):
+ netcfg.append(line)
+ # Now generate the cloud-init portion of sysconfig/network
+ netcfg.extend([_make_header(), 'NETWORKING=yes'])
if network_state.use_ipv6:
netcfg.append('NETWORKING_IPV6=yes')
netcfg.append('IPV6_AUTOCONF=no')
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index 1306a0f..a931a3e 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -1483,7 +1483,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true
BOOTPROTO=none
DEVICE=bond0
DHCPV6C=yes
- IPV6_AUTOCONF=no
IPV6INIT=yes
MACADDR=aa:bb:cc:dd:ee:ff
ONBOOT=yes
--
1.8.3.1

View File

@ -0,0 +1,56 @@
From 9d951d55a1be44bbeb5df485d14d4f84ddf01142 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Mon, 2 Mar 2020 10:46:35 +0100
Subject: Remove race condition between cloud-init and NetworkManager
Message-id: <20200302104635.11648-1-otubo@redhat.com>
Patchwork-id: 94098
O-Subject: [RHEL-7.9/RHEL-8.2.0 cloud-init PATCH] Remove race condition between cloud-init and NetworkManager
Bugzilla: 1807797
RH-Acked-by: Cathy Avery <cavery@redhat.com>
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
BZ: 1748015
BRANCH: rhel7/master-18.5
BREW: 26924611
BZ: 1807797
BRANCH: rhel820/master-18.5
BREW: 26924957
cloud-init service is set to start before NetworkManager service starts,
but this does not avoid a race condition between them. NetworkManager
starts before cloud-init can write `dns=none' to the file:
/etc/NetworkManager/conf.d/99-cloud-init.conf. This way NetworkManager
doesn't read the configuration and erases all resolv.conf values upon
shutdown. On the next reboot neither cloud-init or NetworkManager will
write anything to resolv.conf, leaving it blank.
This patch introduces a NM reload (try-restart) at the end of cloud-init
start up so it won't erase resolv.conf upon first shutdown.
x-downstream-only: yes
resolves: rhbz#1748015, rhbz#1807797 and rhbz#1804780
Signed-off-by: Eduardo Otubo otubo@redhat.com
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
rhel/systemd/cloud-final.service | 2 ++
1 file changed, 2 insertions(+)
diff --git a/rhel/systemd/cloud-final.service b/rhel/systemd/cloud-final.service
index 739b7e3..f303483 100644
--- a/rhel/systemd/cloud-final.service
+++ b/rhel/systemd/cloud-final.service
@@ -11,6 +11,8 @@ ExecStart=/usr/bin/cloud-init modules --mode=final
RemainAfterExit=yes
TimeoutSec=0
KillMode=process
+ExecStartPost=/bin/echo "try restart NetworkManager.service"
+ExecStartPost=/usr/bin/systemctl try-restart NetworkManager.service
# Output needs to appear in instance console output
StandardOutput=journal+console
--
1.8.3.1

View File

@ -0,0 +1,488 @@
From ec14b8ed9cb4264333b80b4361171b1b529c58f3 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Tue, 3 Nov 2020 12:11:45 +0100
Subject: [PATCH 3/5] Add config modules for controlling IBM PowerVM RMC.
(#584)
RH-Author: Eduardo Terrell Ferrari Otubo (eterrell)
RH-MergeRequest: 16: Add config modules for controlling IBM PowerVM RMC. (#584)
RH-Commit: [1/1] 734e2c48d323af31aa36abefae346ef62ba3ef5d (eterrell/cloud-init)
RH-Bugzilla: 1894014
commit f99d4f96b00a9cfec1c721d364cbfd728674e5dc
Author: Aman306 <45781773+Aman306@users.noreply.github.com>
Date: Wed Oct 28 23:36:09 2020 +0530
Add config modules for controlling IBM PowerVM RMC. (#584)
Reliable Scalable Cluster Technology (RSCT) is a set of software
components that together provide a comprehensive clustering
environment(RAS features) for IBM PowerVM based virtual machines. RSCT
includes the Resource Monitoring and Control (RMC) subsystem. RMC is a
generalized framework used for managing, monitoring, and manipulating
resources. RMC runs as a daemon process on individual machines and needs
creation of unique node id and restarts during VM boot.
LP: #1895979
Co-authored-by: Scott Moser <smoser@brickies.net>
Conflicts:
* Calls to module subp.* are replaced by old calls to util.* since the
patch that groups subp.* calls into its own module are introduced after
19.4 release - and it's a huge reafctoring not worth the cherry-pick.
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
---
cloudinit/config/cc_refresh_rmc_and_interface.py | 158 +++++++++++++++++++++
cloudinit/config/cc_reset_rmc.py | 142 ++++++++++++++++++
config/cloud.cfg.tmpl | 2 +
.../test_handler_refresh_rmc_and_interface.py | 109 ++++++++++++++
4 files changed, 411 insertions(+)
create mode 100644 cloudinit/config/cc_refresh_rmc_and_interface.py
create mode 100644 cloudinit/config/cc_reset_rmc.py
create mode 100644 tests/unittests/test_handler/test_handler_refresh_rmc_and_interface.py
diff --git a/cloudinit/config/cc_refresh_rmc_and_interface.py b/cloudinit/config/cc_refresh_rmc_and_interface.py
new file mode 100644
index 0000000..07050c4
--- /dev/null
+++ b/cloudinit/config/cc_refresh_rmc_and_interface.py
@@ -0,0 +1,158 @@
+# (c) Copyright IBM Corp. 2020 All Rights Reserved
+#
+# Author: Aman Kumar Sinha <amansi26@in.ibm.com>
+#
+# This file is part of cloud-init. See LICENSE file for license information.
+
+"""
+Refresh IPv6 interface and RMC
+------------------------------
+**Summary:** Ensure Network Manager is not managing IPv6 interface
+
+This module is IBM PowerVM Hypervisor specific
+
+Reliable Scalable Cluster Technology (RSCT) is a set of software components
+that together provide a comprehensive clustering environment(RAS features)
+for IBM PowerVM based virtual machines. RSCT includes the Resource
+Monitoring and Control (RMC) subsystem. RMC is a generalized framework used
+for managing, monitoring, and manipulating resources. RMC runs as a daemon
+process on individual machines and needs creation of unique node id and
+restarts during VM boot.
+More details refer
+https://www.ibm.com/support/knowledgecenter/en/SGVKBA_3.2/admin/bl503_ovrv.htm
+
+This module handles
+- Refreshing RMC
+- Disabling NetworkManager from handling IPv6 interface, as IPv6 interface
+ is used for communication between RMC daemon and PowerVM hypervisor.
+
+**Internal name:** ``cc_refresh_rmc_and_interface``
+
+**Module frequency:** per always
+
+**Supported distros:** RHEL
+
+"""
+
+from cloudinit import log as logging
+from cloudinit.settings import PER_ALWAYS
+from cloudinit import util
+from cloudinit import netinfo
+
+import errno
+
+frequency = PER_ALWAYS
+
+LOG = logging.getLogger(__name__)
+# Ensure that /opt/rsct/bin has been added to standard PATH of the
+# distro. The symlink to rmcctrl is /usr/sbin/rsct/bin/rmcctrl .
+RMCCTRL = 'rmcctrl'
+
+
+def handle(name, _cfg, _cloud, _log, _args):
+ if not util.which(RMCCTRL):
+ LOG.debug("No '%s' in path, disabled", RMCCTRL)
+ return
+
+ LOG.debug(
+ 'Making the IPv6 up explicitly. '
+ 'Ensuring IPv6 interface is not being handled by NetworkManager '
+ 'and it is restarted to re-establish the communication with '
+ 'the hypervisor')
+
+ ifaces = find_ipv6_ifaces()
+
+ # Setting NM_CONTROLLED=no for IPv6 interface
+ # making it down and up
+
+ if len(ifaces) == 0:
+ LOG.debug("Did not find any interfaces with ipv6 addresses.")
+ else:
+ for iface in ifaces:
+ refresh_ipv6(iface)
+ disable_ipv6(sysconfig_path(iface))
+ restart_network_manager()
+
+
+def find_ipv6_ifaces():
+ info = netinfo.netdev_info()
+ ifaces = []
+ for iface, data in info.items():
+ if iface == "lo":
+ LOG.debug('Skipping localhost interface')
+ if len(data.get("ipv4", [])) != 0:
+ # skip this interface, as it has ipv4 addrs
+ continue
+ ifaces.append(iface)
+ return ifaces
+
+
+def refresh_ipv6(interface):
+ # IPv6 interface is explicitly brought up, subsequent to which the
+ # RMC services are restarted to re-establish the communication with
+ # the hypervisor.
+ util.subp(['ip', 'link', 'set', interface, 'down'])
+ util.subp(['ip', 'link', 'set', interface, 'up'])
+
+
+def sysconfig_path(iface):
+ return '/etc/sysconfig/network-scripts/ifcfg-' + iface
+
+
+def restart_network_manager():
+ util.subp(['systemctl', 'restart', 'NetworkManager'])
+
+
+def disable_ipv6(iface_file):
+ # Ensuring that the communication b/w the hypervisor and VM is not
+ # interrupted due to NetworkManager. For this purpose, as part of
+ # this function, the NM_CONTROLLED is explicitly set to No for IPV6
+ # interface and NetworkManager is restarted.
+ try:
+ contents = util.load_file(iface_file)
+ except IOError as e:
+ if e.errno == errno.ENOENT:
+ LOG.debug("IPv6 interface file %s does not exist\n",
+ iface_file)
+ else:
+ raise e
+
+ if 'IPV6INIT' not in contents:
+ LOG.debug("Interface file %s did not have IPV6INIT", iface_file)
+ return
+
+ LOG.debug("Editing interface file %s ", iface_file)
+
+ # Dropping any NM_CONTROLLED or IPV6 lines from IPv6 interface file.
+ lines = contents.splitlines()
+ lines = [line for line in lines if not search(line)]
+ lines.append("NM_CONTROLLED=no")
+
+ with open(iface_file, "w") as fp:
+ fp.write("\n".join(lines) + "\n")
+
+
+def search(contents):
+ # Search for any NM_CONTROLLED or IPV6 lines in IPv6 interface file.
+ return(
+ contents.startswith("IPV6ADDR") or
+ contents.startswith("IPADDR6") or
+ contents.startswith("IPV6INIT") or
+ contents.startswith("NM_CONTROLLED"))
+
+
+def refresh_rmc():
+ # To make a healthy connection between RMC daemon and hypervisor we
+ # refresh RMC. With refreshing RMC we are ensuring that making IPv6
+ # down and up shouldn't impact communication between RMC daemon and
+ # hypervisor.
+ # -z : stop Resource Monitoring & Control subsystem and all resource
+ # managers, but the command does not return control to the user
+ # until the subsystem and all resource managers are stopped.
+ # -s : start Resource Monitoring & Control subsystem.
+ try:
+ util.subp([RMCCTRL, '-z'])
+ util.subp([RMCCTRL, '-s'])
+ except Exception:
+ util.logexc(LOG, 'Failed to refresh the RMC subsystem.')
+ raise
diff --git a/cloudinit/config/cc_reset_rmc.py b/cloudinit/config/cc_reset_rmc.py
new file mode 100644
index 0000000..68373ad
--- /dev/null
+++ b/cloudinit/config/cc_reset_rmc.py
@@ -0,0 +1,142 @@
+# (c) Copyright IBM Corp. 2020 All Rights Reserved
+#
+# Author: Aman Kumar Sinha <amansi26@in.ibm.com>
+#
+# This file is part of cloud-init. See LICENSE file for license information.
+
+
+"""
+Reset RMC
+------------
+**Summary:** reset rsct node id
+
+Reset RMC module is IBM PowerVM Hypervisor specific
+
+Reliable Scalable Cluster Technology (RSCT) is a set of software components,
+that together provide a comprehensive clustering environment (RAS features)
+for IBM PowerVM based virtual machines. RSCT includes the Resource monitoring
+and control (RMC) subsystem. RMC is a generalized framework used for managing,
+monitoring, and manipulating resources. RMC runs as a daemon process on
+individual machines and needs creation of unique node id and restarts
+during VM boot.
+More details refer
+https://www.ibm.com/support/knowledgecenter/en/SGVKBA_3.2/admin/bl503_ovrv.htm
+
+This module handles
+- creation of the unique RSCT node id to every instance/virtual machine
+ and ensure once set, it isn't changed subsequently by cloud-init.
+ In order to do so, it restarts RSCT service.
+
+Prerequisite of using this module is to install RSCT packages.
+
+**Internal name:** ``cc_reset_rmc``
+
+**Module frequency:** per instance
+
+**Supported distros:** rhel, sles and ubuntu
+
+"""
+import os
+
+from cloudinit import log as logging
+from cloudinit.settings import PER_INSTANCE
+from cloudinit import util
+
+frequency = PER_INSTANCE
+
+# RMCCTRL is expected to be in system PATH (/opt/rsct/bin)
+# The symlink for RMCCTRL and RECFGCT are
+# /usr/sbin/rsct/bin/rmcctrl and
+# /usr/sbin/rsct/install/bin/recfgct respectively.
+RSCT_PATH = '/opt/rsct/install/bin'
+RMCCTRL = 'rmcctrl'
+RECFGCT = 'recfgct'
+
+LOG = logging.getLogger(__name__)
+
+NODE_ID_FILE = '/etc/ct_node_id'
+
+
+def handle(name, _cfg, cloud, _log, _args):
+ # Ensuring node id has to be generated only once during first boot
+ if cloud.datasource.platform_type == 'none':
+ LOG.debug('Skipping creation of new ct_node_id node')
+ return
+
+ if not os.path.isdir(RSCT_PATH):
+ LOG.debug("module disabled, RSCT_PATH not present")
+ return
+
+ orig_path = os.environ.get('PATH')
+ try:
+ add_path(orig_path)
+ reset_rmc()
+ finally:
+ if orig_path:
+ os.environ['PATH'] = orig_path
+ else:
+ del os.environ['PATH']
+
+
+def reconfigure_rsct_subsystems():
+ # Reconfigure the RSCT subsystems, which includes removing all RSCT data
+ # under the /var/ct directory, generating a new node ID, and making it
+ # appear as if the RSCT components were just installed
+ try:
+ out = util.subp([RECFGCT])[0]
+ LOG.debug(out.strip())
+ return out
+ except util.ProcessExecutionError:
+ util.logexc(LOG, 'Failed to reconfigure the RSCT subsystems.')
+ raise
+
+
+def get_node_id():
+ try:
+ fp = util.load_file(NODE_ID_FILE)
+ node_id = fp.split('\n')[0]
+ return node_id
+ except Exception:
+ util.logexc(LOG, 'Failed to get node ID from file %s.' % NODE_ID_FILE)
+ raise
+
+
+def add_path(orig_path):
+ # Adding the RSCT_PATH to env standard path
+ # So thet cloud init automatically find and
+ # run RECFGCT to create new node_id.
+ suff = ":" + orig_path if orig_path else ""
+ os.environ['PATH'] = RSCT_PATH + suff
+ return os.environ['PATH']
+
+
+def rmcctrl():
+ # Stop the RMC subsystem and all resource managers so that we can make
+ # some changes to it
+ try:
+ return util.subp([RMCCTRL, '-z'])
+ except Exception:
+ util.logexc(LOG, 'Failed to stop the RMC subsystem.')
+ raise
+
+
+def reset_rmc():
+ LOG.debug('Attempting to reset RMC.')
+
+ node_id_before = get_node_id()
+ LOG.debug('Node ID at beginning of module: %s', node_id_before)
+
+ # Stop the RMC subsystem and all resource managers so that we can make
+ # some changes to it
+ rmcctrl()
+ reconfigure_rsct_subsystems()
+
+ node_id_after = get_node_id()
+ LOG.debug('Node ID at end of module: %s', node_id_after)
+
+ # Check if new node ID is generated or not
+ # by comparing old and new node ID
+ if node_id_after == node_id_before:
+ msg = 'New node ID did not get generated.'
+ LOG.error(msg)
+ raise Exception(msg)
diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl
index 87c37ba..52a259c 100644
--- a/config/cloud.cfg.tmpl
+++ b/config/cloud.cfg.tmpl
@@ -121,6 +121,8 @@ cloud_final_modules:
- mcollective
{% endif %}
- salt-minion
+ - reset_rmc
+ - refresh_rmc_and_interface
- rightscale_userdata
- scripts-vendor
- scripts-per-once
diff --git a/tests/unittests/test_handler/test_handler_refresh_rmc_and_interface.py b/tests/unittests/test_handler/test_handler_refresh_rmc_and_interface.py
new file mode 100644
index 0000000..0c35710
--- /dev/null
+++ b/tests/unittests/test_handler/test_handler_refresh_rmc_and_interface.py
@@ -0,0 +1,109 @@
+from cloudinit.config import cc_refresh_rmc_and_interface as ccrmci
+
+from cloudinit import util
+
+from cloudinit.tests import helpers as t_help
+from cloudinit.tests.helpers import mock
+
+from textwrap import dedent
+import logging
+
+LOG = logging.getLogger(__name__)
+MPATH = "cloudinit.config.cc_refresh_rmc_and_interface"
+NET_INFO = {
+ 'lo': {'ipv4': [{'ip': '127.0.0.1',
+ 'bcast': '', 'mask': '255.0.0.0',
+ 'scope': 'host'}],
+ 'ipv6': [{'ip': '::1/128',
+ 'scope6': 'host'}], 'hwaddr': '',
+ 'up': 'True'},
+ 'env2': {'ipv4': [{'ip': '8.0.0.19',
+ 'bcast': '8.0.0.255', 'mask': '255.255.255.0',
+ 'scope': 'global'}],
+ 'ipv6': [{'ip': 'fe80::f896:c2ff:fe81:8220/64',
+ 'scope6': 'link'}], 'hwaddr': 'fa:96:c2:81:82:20',
+ 'up': 'True'},
+ 'env3': {'ipv4': [{'ip': '90.0.0.14',
+ 'bcast': '90.0.0.255', 'mask': '255.255.255.0',
+ 'scope': 'global'}],
+ 'ipv6': [{'ip': 'fe80::f896:c2ff:fe81:8221/64',
+ 'scope6': 'link'}], 'hwaddr': 'fa:96:c2:81:82:21',
+ 'up': 'True'},
+ 'env4': {'ipv4': [{'ip': '9.114.23.7',
+ 'bcast': '9.114.23.255', 'mask': '255.255.255.0',
+ 'scope': 'global'}],
+ 'ipv6': [{'ip': 'fe80::f896:c2ff:fe81:8222/64',
+ 'scope6': 'link'}], 'hwaddr': 'fa:96:c2:81:82:22',
+ 'up': 'True'},
+ 'env5': {'ipv4': [],
+ 'ipv6': [{'ip': 'fe80::9c26:c3ff:fea4:62c8/64',
+ 'scope6': 'link'}], 'hwaddr': '42:20:86:df:fa:4c',
+ 'up': 'True'}}
+
+
+class TestRsctNodeFile(t_help.CiTestCase):
+ def test_disable_ipv6_interface(self):
+ """test parsing of iface files."""
+ fname = self.tmp_path("iface-eth5")
+ util.write_file(fname, dedent("""\
+ BOOTPROTO=static
+ DEVICE=eth5
+ HWADDR=42:20:86:df:fa:4c
+ IPV6INIT=yes
+ IPADDR6=fe80::9c26:c3ff:fea4:62c8/64
+ IPV6ADDR=fe80::9c26:c3ff:fea4:62c8/64
+ NM_CONTROLLED=yes
+ ONBOOT=yes
+ STARTMODE=auto
+ TYPE=Ethernet
+ USERCTL=no
+ """))
+
+ ccrmci.disable_ipv6(fname)
+ self.assertEqual(dedent("""\
+ BOOTPROTO=static
+ DEVICE=eth5
+ HWADDR=42:20:86:df:fa:4c
+ ONBOOT=yes
+ STARTMODE=auto
+ TYPE=Ethernet
+ USERCTL=no
+ NM_CONTROLLED=no
+ """), util.load_file(fname))
+
+ @mock.patch(MPATH + '.refresh_rmc')
+ @mock.patch(MPATH + '.restart_network_manager')
+ @mock.patch(MPATH + '.disable_ipv6')
+ @mock.patch(MPATH + '.refresh_ipv6')
+ @mock.patch(MPATH + '.netinfo.netdev_info')
+ @mock.patch(MPATH + '.util.which')
+ def test_handle(self, m_refresh_rmc,
+ m_netdev_info, m_refresh_ipv6, m_disable_ipv6,
+ m_restart_nm, m_which):
+ """Basic test of handle."""
+ m_netdev_info.return_value = NET_INFO
+ m_which.return_value = '/opt/rsct/bin/rmcctrl'
+ ccrmci.handle(
+ "refresh_rmc_and_interface", None, None, None, None)
+ self.assertEqual(1, m_netdev_info.call_count)
+ m_refresh_ipv6.assert_called_with('env5')
+ m_disable_ipv6.assert_called_with(
+ '/etc/sysconfig/network-scripts/ifcfg-env5')
+ self.assertEqual(1, m_restart_nm.call_count)
+ self.assertEqual(1, m_refresh_rmc.call_count)
+
+ @mock.patch(MPATH + '.netinfo.netdev_info')
+ def test_find_ipv6(self, m_netdev_info):
+ """find_ipv6_ifaces parses netdev_info returning those with ipv6"""
+ m_netdev_info.return_value = NET_INFO
+ found = ccrmci.find_ipv6_ifaces()
+ self.assertEqual(['env5'], found)
+
+ @mock.patch(MPATH + '.util.subp')
+ def test_refresh_ipv6(self, m_subp):
+ """refresh_ipv6 should ip down and up the interface."""
+ iface = "myeth0"
+ ccrmci.refresh_ipv6(iface)
+ m_subp.assert_has_calls([
+ mock.call(['ip', 'link', 'set', iface, 'down']),
+ mock.call(['ip', 'link', 'set', iface, 'up'])])
--
1.8.3.1

View File

@ -0,0 +1,46 @@
From 65b26a20b550ae301ca33eafe062a873f53969de Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Wed, 24 Jun 2020 07:34:32 +0200
Subject: [PATCH 3/4] Change from redhat to rhel in systemd generator tmpl
(#450)
RH-Author: Eduardo Otubo <otubo@redhat.com>
Message-id: <20200623154034.28563-3-otubo@redhat.com>
Patchwork-id: 97783
O-Subject: [RHEL-8.3.0/RHEL-8.2.1 cloud-init PATCH 2/3] Change from redhat to rhel in systemd generator tmpl (#450)
Bugzilla: 1834173
RH-Acked-by: Cathy Avery <cavery@redhat.com>
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
commit 650d53d656b612442773453813d8417b234d3752
Author: Eduardo Otubo <otubo@redhat.com>
Date: Tue Jun 23 14:41:15 2020 +0200
Change from redhat to rhel in systemd generator tmpl (#450)
The name `redhat' is not used but rather `rhel' to identify the distro.
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
systemd/cloud-init-generator.tmpl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/systemd/cloud-init-generator.tmpl b/systemd/cloud-init-generator.tmpl
index 45efa24..0773356 100755
--- a/systemd/cloud-init-generator.tmpl
+++ b/systemd/cloud-init-generator.tmpl
@@ -83,7 +83,7 @@ default() {
check_for_datasource() {
local ds_rc=""
-{% if variant in ["redhat", "fedora", "centos"] %}
+{% if variant in ["rhel", "fedora", "centos"] %}
local dsidentify="/usr/libexec/cloud-init/ds-identify"
{% else %}
local dsidentify="/usr/lib/cloud-init/ds-identify"
--
1.8.3.1

View File

@ -0,0 +1,47 @@
From d210f4b6c23d2739f76f9ab348090bcf350c5177 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Mon, 31 Aug 2020 09:44:05 +0200
Subject: [PATCH] Changing notation of subp call
RH-Author: Eduardo Otubo <otubo@redhat.com>
Message-id: <20200824142252.16298-1-otubo@redhat.com>
Patchwork-id: 98215
O-Subject: [RHEL-7.9.z/RHEL-8.2.1/RHEL-8.3.0 cloud-init PATCH] Changing notation of subp call
Bugzilla: 1839662
RH-Acked-by: Cathy Avery <cavery@redhat.com>
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
The previous patch was applied upstream on top of a refactoring that moves subp
to its own module (3c551f6e, Move subp into its own module. (#416), release
20.2).
Downstream we're not there yet, in order to avoid applying the above
commit and add a huge refactoring, I'll just change this call and we can
benefit of this changes in a future rebase.
x-downstream-only: yes
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
cloudinit/sources/helpers/vmware/imc/guestcust_util.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cloudinit/sources/helpers/vmware/imc/guestcust_util.py b/cloudinit/sources/helpers/vmware/imc/guestcust_util.py
index a270d9f..816f52e 100644
--- a/cloudinit/sources/helpers/vmware/imc/guestcust_util.py
+++ b/cloudinit/sources/helpers/vmware/imc/guestcust_util.py
@@ -136,8 +136,8 @@ def get_tools_config(section, key, defaultVal):
cmd = ['vmware-toolbox-cmd', 'config', 'get', section, key]
try:
- (outText, _) = subp.subp(cmd)
- except subp.ProcessExecutionError as e:
+ (outText, _) = util.subp(cmd)
+ except util.ProcessExecutionError as e:
if e.exit_code == 69:
logger.debug(
"vmware-toolbox-cmd returned 69 (unavailable) for cmd: %s."
--
1.8.3.1

View File

@ -0,0 +1,115 @@
From 94753da021d0849f4858e2c2cb98b3276842b665 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Mon, 24 Aug 2020 15:34:24 +0200
Subject: [PATCH 1/5] DHCP sandboxing failing on noexec mounted /var/tmp (#521)
RH-Author: Eduardo Terrell Ferrari Otubo (eterrell)
RH-MergeRequest: 1: DHCP sandboxing failing on noexec mounted /var/tmp (#521)
RH-Commit: [1/1] 4971d742aa1de27dff61b07ef9d6d478c0889ded (eterrell/cloud-init)
RH-Bugzilla: 1879989
commit db86753f81af73826158c9522f2521f210300e2b
Author: Eduardo Otubo <otubo@redhat.com>
Date: Mon Aug 24 15:34:24 2020 +0200
DHCP sandboxing failing on noexec mounted /var/tmp (#521)
* DHCP sandboxing failing on noexec mounted /var/tmp
If /var/tmp is mounted with noexec option the DHCP sandboxing will fail
with Permission Denied. This patch simply avoids this error by checking
the exec permission updating the dhcp path in negative case.
rhbz: https://bugzilla.redhat.com/show_bug.cgi?id=1879989
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
* Replacing with os.* calls
* Adding test and removing isfile() useless call.
Co-authored-by: Rick Harding <rharding@mitechie.com>
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
---
cloudinit/net/dhcp.py | 6 ++++++
cloudinit/net/tests/test_dhcp.py | 46 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+)
diff --git a/cloudinit/net/dhcp.py b/cloudinit/net/dhcp.py
index c033cc8..841e72e 100644
--- a/cloudinit/net/dhcp.py
+++ b/cloudinit/net/dhcp.py
@@ -215,6 +215,12 @@ def dhcp_discovery(dhclient_cmd_path, interface, cleandir):
pid_file = os.path.join(cleandir, 'dhclient.pid')
lease_file = os.path.join(cleandir, 'dhcp.leases')
+ # In some cases files in /var/tmp may not be executable, launching dhclient
+ # from there will certainly raise 'Permission denied' error. Try launching
+ # the original dhclient instead.
+ if not os.access(sandbox_dhclient_cmd, os.X_OK):
+ sandbox_dhclient_cmd = dhclient_cmd_path
+
# ISC dhclient needs the interface up to send initial discovery packets.
# Generally dhclient relies on dhclient-script PREINIT action to bring the
# link up before attempting discovery. Since we are using -sf /bin/true,
diff --git a/cloudinit/net/tests/test_dhcp.py b/cloudinit/net/tests/test_dhcp.py
index c3fa1e0..08e2cfb 100644
--- a/cloudinit/net/tests/test_dhcp.py
+++ b/cloudinit/net/tests/test_dhcp.py
@@ -406,6 +406,52 @@ class TestDHCPDiscoveryClean(CiTestCase):
'eth9', '-sf', '/bin/true'], capture=True)])
m_kill.assert_has_calls([mock.call(my_pid, signal.SIGKILL)])
+ @mock.patch('cloudinit.net.dhcp.util.get_proc_ppid')
+ @mock.patch('cloudinit.net.dhcp.os.kill')
+ @mock.patch('cloudinit.net.dhcp.subp.subp')
+ def test_dhcp_discovery_outside_sandbox(self, m_subp, m_kill, m_getppid):
+ """dhcp_discovery brings up the interface and runs dhclient.
+
+ It also returns the parsed dhcp.leases file generated in the sandbox.
+ """
+ m_subp.return_value = ('', '')
+ tmpdir = self.tmp_dir()
+ dhclient_script = os.path.join(tmpdir, 'dhclient.orig')
+ script_content = '#!/bin/bash\necho fake-dhclient'
+ write_file(dhclient_script, script_content, mode=0o755)
+ lease_content = dedent("""
+ lease {
+ interface "eth9";
+ fixed-address 192.168.2.74;
+ option subnet-mask 255.255.255.0;
+ option routers 192.168.2.1;
+ }
+ """)
+ lease_file = os.path.join(tmpdir, 'dhcp.leases')
+ write_file(lease_file, lease_content)
+ pid_file = os.path.join(tmpdir, 'dhclient.pid')
+ my_pid = 1
+ write_file(pid_file, "%d\n" % my_pid)
+ m_getppid.return_value = 1 # Indicate that dhclient has daemonized
+
+ with mock.patch('os.access', return_value=False):
+ self.assertCountEqual(
+ [{'interface': 'eth9', 'fixed-address': '192.168.2.74',
+ 'subnet-mask': '255.255.255.0', 'routers': '192.168.2.1'}],
+ dhcp_discovery(dhclient_script, 'eth9', tmpdir))
+ # dhclient script got copied
+ with open(os.path.join(tmpdir, 'dhclient.orig')) as stream:
+ self.assertEqual(script_content, stream.read())
+ # Interface was brought up before dhclient called from sandbox
+ m_subp.assert_has_calls([
+ mock.call(
+ ['ip', 'link', 'set', 'dev', 'eth9', 'up'], capture=True),
+ mock.call(
+ [os.path.join(tmpdir, 'dhclient.orig'), '-1', '-v', '-lf',
+ lease_file, '-pf', os.path.join(tmpdir, 'dhclient.pid'),
+ 'eth9', '-sf', '/bin/true'], capture=True)])
+ m_kill.assert_has_calls([mock.call(my_pid, signal.SIGKILL)])
+
class TestSystemdParseLeases(CiTestCase):
--
1.8.3.1

View File

@ -0,0 +1,59 @@
From 5691fd1ce3eb430c8da19538b5988eba7da6d2be Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Thu, 21 Jan 2021 09:57:53 +0100
Subject: [PATCH] DataSourceAzure: update password for defuser if exists (#671)
RH-Author: Eduardo Terrell Ferrari Otubo (eterrell)
RH-MergeRequest: 36: DataSourceAzure: update password for defuser if exists (#671)
RH-Commit: [1/1] a834a44ca127480512137b4258ff01e993fbee41 (eterrell/cloud-init)
RH-Bugzilla: 1916839
commit eea754492f074e00b601cf77aa278e3623857c5a
Author: Anh Vo <anhvo@microsoft.com>
Date: Thu Nov 19 00:35:46 2020 -0500
DataSourceAzure: update password for defuser if exists (#671)
cc_set_password will only update the password for the default user if
cfg['password'] is set. The existing code of datasource Azure will fail
to update the default user's password because it does not set that
metadata. If the default user doesn't exist in the image, the current
code works fine because the password is set during user create and
not in cc_set_password
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
---
cloudinit/sources/DataSourceAzure.py | 2 +-
tests/unittests/test_datasource/test_azure.py | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
index 6fb889c4..69454c40 100755
--- a/cloudinit/sources/DataSourceAzure.py
+++ b/cloudinit/sources/DataSourceAzure.py
@@ -1206,7 +1206,7 @@ def read_azure_ovf(contents):
if password:
defuser['lock_passwd'] = False
if DEF_PASSWD_REDACTION != password:
- defuser['passwd'] = encrypt_pass(password)
+ defuser['passwd'] = cfg['password'] = encrypt_pass(password)
if defuser:
cfg['system_info'] = {'default_user': defuser}
diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py
index a809fd87..f141dc6c 100644
--- a/tests/unittests/test_datasource/test_azure.py
+++ b/tests/unittests/test_datasource/test_azure.py
@@ -899,6 +899,9 @@ scbus-1 on xpt0 bus 0
crypt.crypt(odata['UserPassword'],
defuser['passwd'][0:pos]))
+ # the same hashed value should also be present in cfg['password']
+ self.assertEqual(defuser['passwd'], dsrc.cfg['password'])
+
def test_user_not_locked_if_password_redacted(self):
odata = {'HostName': "myhost", 'UserName': "myuser",
'UserPassword': dsaz.DEF_PASSWD_REDACTION}
--
2.18.4

View File

@ -0,0 +1,230 @@
From 17f972b6fb172fe19d6e115a20664eefdbd3838d Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Mon, 24 Aug 2020 15:25:38 +0200
Subject: [PATCH 3/3] Detect kernel version before swap file creation (#428)
RH-Author: Eduardo Otubo <otubo@redhat.com>
Message-id: <20200820092042.5418-4-otubo@redhat.com>
Patchwork-id: 98191
O-Subject: [RHEL-8.3.0 cloud-init PATCH 3/3] Detect kernel version before swap file creation (#428)
Bugzilla: 1794664
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
commit b749548a9eb43b34cce64f8688107645411abc8c
Author: Eduardo Otubo <otubo@redhat.com>
Date: Tue Aug 18 23:12:02 2020 +0200
Detect kernel version before swap file creation (#428)
According to man page `man 8 swapon', "Preallocated swap files are
supported on XFS since Linux 4.18". This patch checks for kernel version
before attepting to create swapfile, using dd for XFS only on kernel
versions <= 4.18 or btrfs.
Add new func util.kernel_version which returns a tuple of ints (major, minor)
Signed-off-by: Eduardo Otubo otubo@redhat.com
Signed-off-by: Eduardo Otubo otubo@redhat.com
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
cloudinit/config/cc_mounts.py | 8 +-
cloudinit/util.py | 4 +
.../unittests/test_handler/test_handler_mounts.py | 107 +++++++++++++++++++++
tests/unittests/test_util.py | 15 +++
4 files changed, 131 insertions(+), 3 deletions(-)
diff --git a/cloudinit/config/cc_mounts.py b/cloudinit/config/cc_mounts.py
index 0573026..e1c43e3 100644
--- a/cloudinit/config/cc_mounts.py
+++ b/cloudinit/config/cc_mounts.py
@@ -65,7 +65,7 @@ swap file is created.
from string import whitespace
import logging
-import os.path
+import os
import re
from cloudinit import type_utils
@@ -249,7 +249,8 @@ def create_swapfile(fname, size):
fstype = util.get_mount_info(swap_dir)[1]
- if fstype in ("xfs", "btrfs"):
+ if (fstype == "xfs" and
+ util.kernel_version() < (4, 18)) or fstype == "btrfs":
create_swap(fname, size, "dd")
else:
try:
@@ -259,7 +260,8 @@ def create_swapfile(fname, size):
LOG.warning("Will attempt with dd.")
create_swap(fname, size, "dd")
- util.chmod(fname, 0o600)
+ if os.path.exists(fname):
+ util.chmod(fname, 0o600)
try:
util.subp(['mkswap', fname])
except util.ProcessExecutionError:
diff --git a/cloudinit/util.py b/cloudinit/util.py
index 5d51ba8..ad89376 100644
--- a/cloudinit/util.py
+++ b/cloudinit/util.py
@@ -79,6 +79,10 @@ CONTAINER_TESTS = (['systemd-detect-virt', '--quiet', '--container'],
['lxc-is-container'])
+def kernel_version():
+ return tuple(map(int, os.uname().release.split('.')[:2]))
+
+
@lru_cache()
def get_architecture(target=None):
out, _ = subp(['dpkg', '--print-architecture'], capture=True,
diff --git a/tests/unittests/test_handler/test_handler_mounts.py b/tests/unittests/test_handler/test_handler_mounts.py
index 7bcefa0..27bcc6f 100644
--- a/tests/unittests/test_handler/test_handler_mounts.py
+++ b/tests/unittests/test_handler/test_handler_mounts.py
@@ -132,6 +132,113 @@ class TestSanitizeDevname(test_helpers.FilesystemMockingTestCase):
'ephemeral0.1', lambda x: disk_path, mock.Mock()))
+class TestSwapFileCreation(test_helpers.FilesystemMockingTestCase):
+
+ def setUp(self):
+ super(TestSwapFileCreation, self).setUp()
+ self.new_root = self.tmp_dir()
+ self.patchOS(self.new_root)
+
+ self.fstab_path = os.path.join(self.new_root, 'etc/fstab')
+ self.swap_path = os.path.join(self.new_root, 'swap.img')
+ self._makedirs('/etc')
+
+ self.add_patch('cloudinit.config.cc_mounts.FSTAB_PATH',
+ 'mock_fstab_path',
+ self.fstab_path,
+ autospec=False)
+
+ self.add_patch('cloudinit.config.cc_mounts.subp.subp',
+ 'm_subp_subp')
+
+ self.add_patch('cloudinit.config.cc_mounts.util.mounts',
+ 'mock_util_mounts',
+ return_value={
+ '/dev/sda1': {'fstype': 'ext4',
+ 'mountpoint': '/',
+ 'opts': 'rw,relatime,discard'
+ }})
+
+ self.mock_cloud = mock.Mock()
+ self.mock_log = mock.Mock()
+ self.mock_cloud.device_name_to_device = self.device_name_to_device
+
+ self.cc = {
+ 'swap': {
+ 'filename': self.swap_path,
+ 'size': '512',
+ 'maxsize': '512'}}
+
+ def _makedirs(self, directory):
+ directory = os.path.join(self.new_root, directory.lstrip('/'))
+ if not os.path.exists(directory):
+ os.makedirs(directory)
+
+ def device_name_to_device(self, path):
+ if path == 'swap':
+ return self.swap_path
+ else:
+ dev = None
+
+ return dev
+
+ @mock.patch('cloudinit.util.get_mount_info')
+ @mock.patch('cloudinit.util.kernel_version')
+ def test_swap_creation_method_fallocate_on_xfs(self, m_kernel_version,
+ m_get_mount_info):
+ m_kernel_version.return_value = (4, 20)
+ m_get_mount_info.return_value = ["", "xfs"]
+
+ cc_mounts.handle(None, self.cc, self.mock_cloud, self.mock_log, [])
+ self.m_subp_subp.assert_has_calls([
+ mock.call(['fallocate', '-l', '0M', self.swap_path], capture=True),
+ mock.call(['mkswap', self.swap_path]),
+ mock.call(['swapon', '-a'])])
+
+ @mock.patch('cloudinit.util.get_mount_info')
+ @mock.patch('cloudinit.util.kernel_version')
+ def test_swap_creation_method_xfs(self, m_kernel_version,
+ m_get_mount_info):
+ m_kernel_version.return_value = (3, 18)
+ m_get_mount_info.return_value = ["", "xfs"]
+
+ cc_mounts.handle(None, self.cc, self.mock_cloud, self.mock_log, [])
+ self.m_subp_subp.assert_has_calls([
+ mock.call(['dd', 'if=/dev/zero',
+ 'of=' + self.swap_path,
+ 'bs=1M', 'count=0'], capture=True),
+ mock.call(['mkswap', self.swap_path]),
+ mock.call(['swapon', '-a'])])
+
+ @mock.patch('cloudinit.util.get_mount_info')
+ @mock.patch('cloudinit.util.kernel_version')
+ def test_swap_creation_method_btrfs(self, m_kernel_version,
+ m_get_mount_info):
+ m_kernel_version.return_value = (4, 20)
+ m_get_mount_info.return_value = ["", "btrfs"]
+
+ cc_mounts.handle(None, self.cc, self.mock_cloud, self.mock_log, [])
+ self.m_subp_subp.assert_has_calls([
+ mock.call(['dd', 'if=/dev/zero',
+ 'of=' + self.swap_path,
+ 'bs=1M', 'count=0'], capture=True),
+ mock.call(['mkswap', self.swap_path]),
+ mock.call(['swapon', '-a'])])
+
+ @mock.patch('cloudinit.util.get_mount_info')
+ @mock.patch('cloudinit.util.kernel_version')
+ def test_swap_creation_method_ext4(self, m_kernel_version,
+ m_get_mount_info):
+ m_kernel_version.return_value = (5, 14)
+ m_get_mount_info.return_value = ["", "ext4"]
+
+ cc_mounts.handle(None, self.cc, self.mock_cloud, self.mock_log, [])
+ self.m_subp_subp.assert_has_calls([
+ mock.call(['fallocate', '-l', '0M', self.swap_path], capture=True),
+ mock.call(['mkswap', self.swap_path]),
+ mock.call(['swapon', '-a'])])
+
+
class TestFstabHandling(test_helpers.FilesystemMockingTestCase):
swap_path = '/dev/sdb1'
diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py
index 0e71db8..87dc8dd 100644
--- a/tests/unittests/test_util.py
+++ b/tests/unittests/test_util.py
@@ -1177,4 +1177,19 @@ class TestGetProcEnv(helpers.TestCase):
my_ppid = os.getppid()
self.assertEqual(my_ppid, util.get_proc_ppid(my_pid))
+
+class TestKernelVersion():
+ """test kernel version function"""
+
+ params = [
+ ('5.6.19-300.fc32.x86_64', (5, 6)),
+ ('4.15.0-101-generic', (4, 15)),
+ ('3.10.0-1062.12.1.vz7.131.10', (3, 10)),
+ ('4.18.0-144.el8.x86_64', (4, 18))]
+
+ @mock.patch('os.uname')
+ @pytest.mark.parametrize("uname_release,expected", params)
+ def test_kernel_version(self, m_uname, uname_release, expected):
+ m_uname.return_value.release = uname_release
+ assert expected == util.kernel_version()
# vi: ts=4 expandtab
--
1.8.3.1

View File

@ -0,0 +1,164 @@
From 49e5a49cc007b2a751eea212b4052e92837ebc8a Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Mon, 24 Aug 2020 15:25:34 +0200
Subject: [PATCH 1/3] Do not use fallocate in swap file creation on xfs. (#70)
RH-Author: Eduardo Otubo <otubo@redhat.com>
Message-id: <20200820092042.5418-2-otubo@redhat.com>
Patchwork-id: 98194
O-Subject: [RHEL-8.3.0 cloud-init PATCH 1/3] Do not use fallocate in swap file creation on xfs. (#70)
Bugzilla: 1794664
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
commit 6603706eec1c39d9d591c8ffa0ef7171b74d84d6
Author: Eduardo Otubo <otubo@redhat.com>
Date: Thu Jan 23 17:41:48 2020 +0100
Do not use fallocate in swap file creation on xfs. (#70)
When creating a swap file on an xfs filesystem, fallocate cannot be used.
Doing so results in failure of swapon and a message like:
swapon: swapfile has holes
The solution here is to maintain a list (currently containing only XFS)
of filesystems where fallocate cannot be used. The, on those fileystems
use the slower but functional 'dd' method.
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Co-authored-by: Adam Dobrawy <naczelnik@jawnosc.tk>
Co-authored-by: Scott Moser <smoser@brickies.net>
Co-authored-by: Daniel Watkins <daniel@daniel-watkins.co.uk>
LP: #1781781
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
cloudinit/config/cc_mounts.py | 67 ++++++++++++++++------
.../unittests/test_handler/test_handler_mounts.py | 12 ++++
2 files changed, 62 insertions(+), 17 deletions(-)
diff --git a/cloudinit/config/cc_mounts.py b/cloudinit/config/cc_mounts.py
index c741c74..4293844 100644
--- a/cloudinit/config/cc_mounts.py
+++ b/cloudinit/config/cc_mounts.py
@@ -223,13 +223,58 @@ def suggested_swapsize(memsize=None, maxsize=None, fsys=None):
return size
+def create_swapfile(fname, size):
+ """Size is in MiB."""
+
+ errmsg = "Failed to create swapfile '%s' of size %dMB via %s: %s"
+
+ def create_swap(fname, size, method):
+ LOG.debug("Creating swapfile in '%s' on fstype '%s' using '%s'",
+ fname, fstype, method)
+
+ if method == "fallocate":
+ cmd = ['fallocate', '-l', '%dM' % size, fname]
+ elif method == "dd":
+ cmd = ['dd', 'if=/dev/zero', 'of=%s' % fname, 'bs=1M',
+ 'count=%d' % size]
+
+ try:
+ util.subp(cmd, capture=True)
+ except util.ProcessExecutionError as e:
+ LOG.warning(errmsg, fname, size, method, e)
+ util.del_file(fname)
+
+ swap_dir = os.path.dirname(fname)
+ util.ensure_dir(swap_dir)
+
+ fstype = util.get_mount_info(swap_dir)[1]
+
+ if fstype in ("xfs", "btrfs"):
+ create_swap(fname, size, "dd")
+ else:
+ try:
+ create_swap(fname, size, "fallocate")
+ except util.ProcessExecutionError as e:
+ LOG.warning(errmsg, fname, size, "dd", e)
+ LOG.warning("Will attempt with dd.")
+ create_swap(fname, size, "dd")
+
+ util.chmod(fname, 0o600)
+ try:
+ util.subp(['mkswap', fname])
+ except util.ProcessExecutionError:
+ util.del_file(fname)
+ raise
+
+
def setup_swapfile(fname, size=None, maxsize=None):
"""
fname: full path string of filename to setup
size: the size to create. set to "auto" for recommended
maxsize: the maximum size
"""
- tdir = os.path.dirname(fname)
+ swap_dir = os.path.dirname(fname)
+ mibsize = str(int(size / (2 ** 20)))
if str(size).lower() == "auto":
try:
memsize = util.read_meminfo()['total']
@@ -237,28 +282,16 @@ def setup_swapfile(fname, size=None, maxsize=None):
LOG.debug("Not creating swap: failed to read meminfo")
return
- util.ensure_dir(tdir)
- size = suggested_swapsize(fsys=tdir, maxsize=maxsize,
+ util.ensure_dir(swap_dir)
+ size = suggested_swapsize(fsys=swap_dir, maxsize=maxsize,
memsize=memsize)
if not size:
LOG.debug("Not creating swap: suggested size was 0")
return
- mbsize = str(int(size / (2 ** 20)))
- msg = "creating swap file '%s' of %sMB" % (fname, mbsize)
- try:
- util.ensure_dir(tdir)
- util.log_time(LOG.debug, msg, func=util.subp,
- args=[['sh', '-c',
- ('rm -f "$1" && umask 0066 && '
- '{ fallocate -l "${2}M" "$1" || '
- 'dd if=/dev/zero "of=$1" bs=1M "count=$2"; } && '
- 'mkswap "$1" || { r=$?; rm -f "$1"; exit $r; }'),
- 'setup_swap', fname, mbsize]])
-
- except Exception as e:
- raise IOError("Failed %s: %s" % (msg, e))
+ util.log_time(LOG.debug, msg="Setting up swap file", func=create_swapfile,
+ args=[fname, mibsize])
return fname
diff --git a/tests/unittests/test_handler/test_handler_mounts.py b/tests/unittests/test_handler/test_handler_mounts.py
index 0fb160b..7bcefa0 100644
--- a/tests/unittests/test_handler/test_handler_mounts.py
+++ b/tests/unittests/test_handler/test_handler_mounts.py
@@ -181,6 +181,18 @@ class TestFstabHandling(test_helpers.FilesystemMockingTestCase):
return dev
+ def test_swap_integrity(self):
+ '''Ensure that the swap file is correctly created and can
+ swapon successfully. Fixing the corner case of:
+ kernel: swapon: swapfile has holes'''
+
+ fstab = '/swap.img swap swap defaults 0 0\n'
+
+ with open(cc_mounts.FSTAB_PATH, 'w') as fd:
+ fd.write(fstab)
+ cc = {'swap': ['filename: /swap.img', 'size: 512', 'maxsize: 512']}
+ cc_mounts.handle(None, cc, self.mock_cloud, self.mock_log, [])
+
def test_fstab_no_swap_device(self):
'''Ensure that cloud-init adds a discovered swap partition
to /etc/fstab.'''
--
1.8.3.1

View File

@ -0,0 +1,41 @@
From 251836a62eb3061b8d26177fd5997a96dccec21b Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Thu, 28 May 2020 08:44:06 +0200
Subject: [PATCH 3/4] Enable ssh_deletekeys by default
RH-Author: Eduardo Otubo <otubo@redhat.com>
Message-id: <20200317091705.15715-1-otubo@redhat.com>
Patchwork-id: 94365
O-Subject: [RHEL-7.9/RHEL-8.2.0 cloud-init PATCH] Enable ssh_deletekeys by default
Bugzilla: 1814152
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
The configuration option ssh_deletekeys will trigger the generation
of new ssh keys for every new instance deployed.
x-downstream-only: yes
resolves: rhbz#1814152
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
rhel/cloud.cfg | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rhel/cloud.cfg b/rhel/cloud.cfg
index 82e8bf6..9ecba21 100644
--- a/rhel/cloud.cfg
+++ b/rhel/cloud.cfg
@@ -6,7 +6,7 @@ ssh_pwauth: 0
mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service', '0', '2']
resize_rootfs_tmp: /dev
-ssh_deletekeys: 0
+ssh_deletekeys: 1
ssh_genkeytypes: ~
syslog_fix_perms: ~
disable_vmware_customization: false
--
1.8.3.1

View File

@ -0,0 +1,303 @@
From 02924179d423c919d0d46e6149da5bb8d26dd0d5 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Tue, 3 Nov 2020 12:16:37 +0100
Subject: [PATCH 4/5] Explicit set IPV6_AUTOCONF and IPV6_FORCE_ACCEPT_RA on
static6 (#634)
RH-Author: Eduardo Terrell Ferrari Otubo (eterrell)
RH-MergeRequest: 17: Explicit set IPV6_AUTOCONF and IPV6_FORCE_ACCEPT_RA on static6 (#634)
RH-Commit: [1/2] ba604c675f7c54a3e1768945a9ba77918ca4a57b (eterrell/cloud-init)
RH-Bugzilla: 1894015
commit b46e4a8cff667c8441622089cf7d57aeb88220cd
Author: Eduardo Otubo <otubo@redhat.com>
Date: Thu Oct 29 15:05:42 2020 +0100
Explicit set IPV6_AUTOCONF and IPV6_FORCE_ACCEPT_RA on static6 (#634)
The static and static6 subnet types for network_data.json were
being ignored by the Openstack handler, this would cause the code to
break and not function properly.
As of today, if a static6 configuration is chosen, the interface will
still eventually be available to receive router advertisements or be set
from NetworkManager to wait for them and cycle the interface in negative
case.
It is safe to assume that if the interface is manually configured to use
static ipv6 address, there's no need to wait for router advertisements.
This patch will set automatically IPV6_AUTOCONF and IPV6_FORCE_ACCEPT_RA
both to "no" in this case.
This patch fixes the specific behavior only for RHEL flavor and
sysconfig renderer. It also introduces new unit tests for the specific
case as well as adjusts some existent tests to be compatible with the
new options. This patch also addresses this problem by assigning the
appropriate subnet type for each case on the openstack handler.
rhbz: #1889635
rhbz: #1889635
Signed-off-by: Eduardo Otubo otubo@redhat.com
Conflicts:
* The context of the patches are slightly different from upstream since
the there is more code added around the changes. But nothing interfering
on the patches.
* One minor conflict, removed the "flavor == 'rhel'" check because the
commit that introduced this change is after the 19.4 release. No harm
done since this commit is intended to be shipped to RHEL only anyways.
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
---
cloudinit/net/network_state.py | 3 +-
cloudinit/net/sysconfig.py | 4 +
cloudinit/sources/helpers/openstack.py | 8 +-
tests/unittests/test_distros/test_netconfig.py | 2 +
tests/unittests/test_net.py | 100 +++++++++++++++++++++++++
5 files changed, 115 insertions(+), 2 deletions(-)
diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py
index f3e8e25..2525fc9 100644
--- a/cloudinit/net/network_state.py
+++ b/cloudinit/net/network_state.py
@@ -822,7 +822,8 @@ def _normalize_subnet(subnet):
if subnet.get('type') in ('static', 'static6'):
normal_subnet.update(
- _normalize_net_keys(normal_subnet, address_keys=('address',)))
+ _normalize_net_keys(normal_subnet, address_keys=(
+ 'address', 'ip_address',)))
normal_subnet['routes'] = [_normalize_route(r)
for r in subnet.get('routes', [])]
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index 4b4ed09..4210544 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -401,6 +401,10 @@ class Renderer(renderer.Renderer):
' because ipv4 subnet-level mtu:%s provided.',
iface_cfg.name, iface_cfg[mtu_key], subnet['mtu'])
iface_cfg[mtu_key] = subnet['mtu']
+
+ if subnet_is_ipv6(subnet):
+ iface_cfg['IPV6_FORCE_ACCEPT_RA'] = False
+ iface_cfg['IPV6_AUTOCONF'] = False
elif subnet_type == 'manual':
# If the subnet has an MTU setting, then ONBOOT=True
# to apply the setting
diff --git a/cloudinit/sources/helpers/openstack.py b/cloudinit/sources/helpers/openstack.py
index 0778f45..6ef4f90 100644
--- a/cloudinit/sources/helpers/openstack.py
+++ b/cloudinit/sources/helpers/openstack.py
@@ -592,11 +592,17 @@ def convert_net_json(network_json=None, known_macs=None):
elif network['type'] in ['ipv6_slaac', 'ipv6_dhcpv6-stateless',
'ipv6_dhcpv6-stateful']:
subnet.update({'type': network['type']})
- elif network['type'] in ['ipv4', 'ipv6']:
+ elif network['type'] in ['ipv4', 'static']:
subnet.update({
'type': 'static',
'address': network.get('ip_address'),
})
+ elif network['type'] in ['ipv6', 'static6']:
+ cfg.update({'accept-ra': False})
+ subnet.update({
+ 'type': 'static6',
+ 'address': network.get('ip_address'),
+ })
# Enable accept_ra for stateful and legacy ipv6_dhcp types
if network['type'] in ['ipv6_dhcpv6-stateful', 'ipv6_dhcp']:
diff --git a/tests/unittests/test_distros/test_netconfig.py b/tests/unittests/test_distros/test_netconfig.py
index 4ea4203..b85a333 100644
--- a/tests/unittests/test_distros/test_netconfig.py
+++ b/tests/unittests/test_distros/test_netconfig.py
@@ -673,7 +673,9 @@ class TestNetCfgDistroOpensuse(TestNetCfgDistroBase):
IPADDR6=2607:f0d0:1002:0011::2/64
IPV6ADDR=2607:f0d0:1002:0011::2/64
IPV6INIT=yes
+ IPV6_AUTOCONF=no
IPV6_DEFAULTGW=2607:f0d0:1002:0011::1
+ IPV6_FORCE_ACCEPT_RA=no
NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index 2eedb12..b2b7c4b 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -768,7 +768,9 @@ IPADDR6_2=2001:DB10::10/64
IPV6ADDR=2001:DB8::10/64
IPV6ADDR_SECONDARIES="2001:DB9::10/64 2001:DB10::10/64"
IPV6INIT=yes
+IPV6_AUTOCONF=no
IPV6_DEFAULTGW=2001:DB8::1
+IPV6_FORCE_ACCEPT_RA=no
NETMASK=255.255.252.0
ONBOOT=yes
STARTMODE=auto
@@ -1016,6 +1018,8 @@ NETWORK_CONFIGS = {
IPADDR6=2001:1::1/64
IPV6ADDR=2001:1::1/64
IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
NETMASK=255.255.255.0
ONBOOT=yes
STARTMODE=auto
@@ -1201,6 +1205,33 @@ NETWORK_CONFIGS = {
"""),
},
},
+ 'static6': {
+ 'yaml': textwrap.dedent("""\
+ version: 1
+ config:
+ - type: 'physical'
+ name: 'iface0'
+ accept-ra: 'no'
+ subnets:
+ - type: 'static6'
+ address: 2001:1::1/64
+ """).rstrip(' '),
+ 'expected_sysconfig_rhel': {
+ 'ifcfg-iface0': textwrap.dedent("""\
+ BOOTPROTO=none
+ DEVICE=iface0
+ IPV6ADDR=2001:1::1/64
+ IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
+ DEVICE=iface0
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ TYPE=Ethernet
+ USERCTL=no
+ """),
+ },
+ },
'dhcpv6_stateless': {
'expected_eni': textwrap.dedent("""\
auto lo
@@ -1507,6 +1538,8 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true
IPADDR6=2001:1::1/64
IPV6ADDR=2001:1::1/64
IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
IPV6_DEFAULTGW=2001:4800:78ff:1b::1
MACADDR=bb:bb:bb:bb:bb:aa
NETMASK=255.255.255.0
@@ -2067,6 +2100,8 @@ iface bond0 inet6 static
IPADDR6=2001:1::1/92
IPV6ADDR=2001:1::1/92
IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
MTU=9000
NETMASK=255.255.255.0
NETMASK1=255.255.255.0
@@ -2154,6 +2189,8 @@ iface bond0 inet6 static
IPADDR6=2001:1::bbbb/96
IPV6ADDR=2001:1::bbbb/96
IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
IPV6_DEFAULTGW=2001:1::1
MTU=2222
NETMASK=255.255.255.0
@@ -2213,6 +2250,9 @@ iface bond0 inet6 static
IPADDR6=2001:1::100/96
IPV6ADDR=2001:1::100/96
IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
+ NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -2226,6 +2266,9 @@ iface bond0 inet6 static
IPADDR6=2001:1::101/96
IPV6ADDR=2001:1::101/96
IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
+ NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
@@ -3015,6 +3058,61 @@ USERCTL=no
self._compare_files_to_expected(entry[self.expected_name], found)
self._assert_headers(found)
+ def test_stattic6_from_json(self):
+ net_json = {
+ "services": [{"type": "dns", "address": "172.19.0.12"}],
+ "networks": [{
+ "network_id": "dacd568d-5be6-4786-91fe-750c374b78b4",
+ "type": "ipv4", "netmask": "255.255.252.0",
+ "link": "tap1a81968a-79",
+ "routes": [{
+ "netmask": "0.0.0.0",
+ "network": "0.0.0.0",
+ "gateway": "172.19.3.254",
+ }, {
+ "netmask": "0.0.0.0", # A second default gateway
+ "network": "0.0.0.0",
+ "gateway": "172.20.3.254",
+ }],
+ "ip_address": "172.19.1.34", "id": "network0"
+ }, {
+ "network_id": "mgmt",
+ "netmask": "ffff:ffff:ffff:ffff::",
+ "link": "interface1",
+ "mode": "link-local",
+ "routes": [],
+ "ip_address": "fe80::c096:67ff:fe5c:6e84",
+ "type": "static6",
+ "id": "network1",
+ "services": [],
+ "accept-ra": "false"
+ }],
+ "links": [
+ {
+ "ethernet_mac_address": "fa:16:3e:ed:9a:59",
+ "mtu": None, "type": "bridge", "id":
+ "tap1a81968a-79",
+ "vif_id": "1a81968a-797a-400f-8a80-567f997eb93f"
+ },
+ ],
+ }
+ macs = {'fa:16:3e:ed:9a:59': 'eth0'}
+ render_dir = self.tmp_dir()
+ network_cfg = openstack.convert_net_json(net_json, known_macs=macs)
+ ns = network_state.parse_net_config_data(network_cfg,
+ skip_broken=False)
+ renderer = self._get_renderer()
+ with self.assertRaises(ValueError):
+ renderer.render_network_state(ns, target=render_dir)
+ self.assertEqual([], os.listdir(render_dir))
+
+ def test_static6_from_yaml(self):
+ entry = NETWORK_CONFIGS['static6']
+ found = self._render_and_read(network_config=yaml.load(
+ entry['yaml']))
+ self._compare_files_to_expected(entry[self.expected_name], found)
+ self._assert_headers(found)
+
def test_dhcpv6_reject_ra_config_v2(self):
entry = NETWORK_CONFIGS['dhcpv6_reject_ra']
found = self._render_and_read(network_config=yaml.load(
@@ -3133,6 +3231,8 @@ USERCTL=no
IPADDR6=2001:db8::100/32
IPV6ADDR=2001:db8::100/32
IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
IPV6_DEFAULTGW=2001:db8::1
NETMASK=255.255.255.0
NM_CONTROLLED=no
--
1.8.3.1

View File

@ -0,0 +1,40 @@
From 301b1770d3e2580c3ee168261a9a97d143cc5f59 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Mon, 1 Jun 2020 11:58:06 +0200
Subject: [PATCH] Make cloud-init.service execute after network is up
RH-Author: Eduardo Otubo <otubo@redhat.com>
Message-id: <20200526090804.2047-1-otubo@redhat.com>
Patchwork-id: 96809
O-Subject: [RHEL-8.2.1 cloud-init PATCH] Make cloud-init.service execute after network is up
Bugzilla: 1803928
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
cloud-init.service needs to wait until network is fully up before
continuing executing and configuring its service.
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
x-downstream-only: yes
Resolves: rhbz#1831646
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
rhel/systemd/cloud-init.service | 1 +
1 file changed, 1 insertion(+)
diff --git a/rhel/systemd/cloud-init.service b/rhel/systemd/cloud-init.service
index d0023a0..0b3d796 100644
--- a/rhel/systemd/cloud-init.service
+++ b/rhel/systemd/cloud-init.service
@@ -5,6 +5,7 @@ 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
--
1.8.3.1

View File

@ -0,0 +1,52 @@
From 0422ba0e773d1a8257a3f2bf3db05f3bc7917eb7 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Thu, 28 May 2020 08:44:08 +0200
Subject: [PATCH 4/4] Remove race condition between cloud-init and
NetworkManager
RH-Author: Eduardo Otubo <otubo@redhat.com>
Message-id: <20200327121911.17699-1-otubo@redhat.com>
Patchwork-id: 94453
O-Subject: [RHEL-7.9/RHEL-8.2.0 cloud-init PATCHv2] Remove race condition between cloud-init and NetworkManager
Bugzilla: 1840648
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Cathy Avery <cavery@redhat.com>
cloud-init service is set to start before NetworkManager service starts,
but this does not avoid a race condition between them. NetworkManager
starts before cloud-init can write `dns=none' to the file:
/etc/NetworkManager/conf.d/99-cloud-init.conf. This way NetworkManager
doesn't read the configuration and erases all resolv.conf values upon
shutdown. On the next reboot neither cloud-init or NetworkManager will
write anything to resolv.conf, leaving it blank.
This patch introduces a NM reload (try-reload-or-restart) at the end of cloud-init
start up so it won't erase resolv.conf upon first shutdown.
x-downstream-only: yes
Signed-off-by: Eduardo Otubo otubo@redhat.com
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
rhel/systemd/cloud-final.service | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/rhel/systemd/cloud-final.service b/rhel/systemd/cloud-final.service
index f303483..05add07 100644
--- a/rhel/systemd/cloud-final.service
+++ b/rhel/systemd/cloud-final.service
@@ -11,8 +11,8 @@ ExecStart=/usr/bin/cloud-init modules --mode=final
RemainAfterExit=yes
TimeoutSec=0
KillMode=process
-ExecStartPost=/bin/echo "try restart NetworkManager.service"
-ExecStartPost=/usr/bin/systemctl try-restart NetworkManager.service
+ExecStartPost=/bin/echo "trying to reload or restart NetworkManager.service"
+ExecStartPost=/usr/bin/systemctl try-reload-or-restart NetworkManager.service
# Output needs to appear in instance console output
StandardOutput=journal+console
--
1.8.3.1

View File

@ -0,0 +1,89 @@
From 07755100b11abd4d429577f9f3f57a2c43592089 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Mon, 17 Aug 2020 11:14:45 +0200
Subject: [PATCH 1/2] When tools.conf does not exist, running cmd
"vmware-toolbox-cmd config get deployPkg enable-custom-scripts", the return
code will be EX_UNAVAILABLE(69), on this condition, it should not take it as
error. (#413)
RH-Author: Eduardo Otubo <otubo@redhat.com>
Message-id: <20200710094434.9711-1-otubo@redhat.com>
Patchwork-id: 97934
O-Subject: [RHEL-7.9.z/RHEL-8.2.1/RHEL-8.3.0 cloud-init PATCH] When tools.conf does not exist, running cmd "vmware-toolbox-cmd config get deployPkg enable-custom-scripts", the return code will be EX_UNAVAILABLE(69), on this condition, it should not take it as error. (#413)
Bugzilla: 1839662
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
From: chengcheng-chcheng <63850735+chengcheng-chcheng@users.noreply.github.com>
The diff seems slightly different from upstream because of some parts
being in different positions. But the final result is the file patched
guestcust_util.py (within this block) exactly identical to the one
upstream.
Also: Sorry for the commit message being just a Subject and this being
enormous. I kept the original from upstream.
commit c6d09af67626c2f2241c64c10c9e27e8752ba87b
Author: chengcheng-chcheng <63850735+chengcheng-chcheng@users.noreply.github.com>
Date: Wed Jun 10 00:20:47 2020 +0800
When tools.conf does not exist, running cmd "vmware-toolbox-cmd config get deployPkg enable-custom-scripts", the return code will be EX_UNAVAILABLE(69), on this condition, it should not take it as error. (#413)
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
.../sources/helpers/vmware/imc/guestcust_util.py | 33 +++++++++++++---------
1 file changed, 20 insertions(+), 13 deletions(-)
diff --git a/cloudinit/sources/helpers/vmware/imc/guestcust_util.py b/cloudinit/sources/helpers/vmware/imc/guestcust_util.py
index 3d369d0..a270d9f 100644
--- a/cloudinit/sources/helpers/vmware/imc/guestcust_util.py
+++ b/cloudinit/sources/helpers/vmware/imc/guestcust_util.py
@@ -133,23 +133,30 @@ def get_tools_config(section, key, defaultVal):
'vmware-toolbox-cmd not installed, returning default value')
return defaultVal
- retValue = defaultVal
cmd = ['vmware-toolbox-cmd', 'config', 'get', section, key]
try:
- (outText, _) = util.subp(cmd)
- m = re.match(r'([^=]+)=(.*)', outText)
- if m:
- retValue = m.group(2).strip()
- logger.debug("Get tools config: [%s] %s = %s",
- section, key, retValue)
- else:
+ (outText, _) = subp.subp(cmd)
+ except subp.ProcessExecutionError as e:
+ if e.exit_code == 69:
logger.debug(
- "Tools config: [%s] %s is not found, return default value: %s",
- section, key, retValue)
- except util.ProcessExecutionError as e:
- logger.error("Failed running %s[%s]", cmd, e.exit_code)
- logger.exception(e)
+ "vmware-toolbox-cmd returned 69 (unavailable) for cmd: %s."
+ " Return default value: %s", " ".join(cmd), defaultVal)
+ else:
+ logger.error("Failed running %s[%s]", cmd, e.exit_code)
+ logger.exception(e)
+ return defaultVal
+
+ retValue = defaultVal
+ m = re.match(r'([^=]+)=(.*)', outText)
+ if m:
+ retValue = m.group(2).strip()
+ logger.debug("Get tools config: [%s] %s = %s",
+ section, key, retValue)
+ else:
+ logger.debug(
+ "Tools config: [%s] %s is not found, return default value: %s",
+ section, key, retValue)
return retValue
--
1.8.3.1

View File

@ -0,0 +1,90 @@
From c3a019b57cade8e6c3963f6bd2c7c15cd67e561c Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Wed, 2 Sep 2020 14:59:06 +0200
Subject: [PATCH] cc_mounts: fix incorrect format specifiers (#316)
RH-Author: Eduardo Otubo <otubo@redhat.com>
Message-id: <20200825131749.4989-1-otubo@redhat.com>
Patchwork-id: 98217
O-Subject: [RHEL-8.3.0 cloud-init PATCH] cc_mounts: fix incorrect format specifiers (#316)
Bugzilla: 1794664
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
RH-Acked-by: Cathy Avery <cavery@redhat.com>
Conflicts: Not exactly a conflict, but removed optional notations
"variable: type" and "-> type" from function header create_swapfile() as
it is only available on Python >= 3.5 and this patch is for RHEL-7.9
only (Python 2.*). The rest of the cherry-pick was clean.
commit 9d7b35ce23aaf8741dd49b16e359c96591be3c76
Author: Daniel Watkins <oddbloke@ubuntu.com>
Date: Wed Apr 15 16:53:08 2020 -0400
cc_mounts: fix incorrect format specifiers (#316)
LP: #1872836
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
cloudinit/config/cc_mounts.py | 6 +++---
cloudinit/config/tests/test_mounts.py | 22 ++++++++++++++++++++++
2 files changed, 25 insertions(+), 3 deletions(-)
create mode 100644 cloudinit/config/tests/test_mounts.py
diff --git a/cloudinit/config/cc_mounts.py b/cloudinit/config/cc_mounts.py
index e1c43e3..55b6770 100644
--- a/cloudinit/config/cc_mounts.py
+++ b/cloudinit/config/cc_mounts.py
@@ -226,17 +226,17 @@ def suggested_swapsize(memsize=None, maxsize=None, fsys=None):
def create_swapfile(fname, size):
"""Size is in MiB."""
- errmsg = "Failed to create swapfile '%s' of size %dMB via %s: %s"
+ errmsg = "Failed to create swapfile '%s' of size %sMB via %s: %s"
def create_swap(fname, size, method):
LOG.debug("Creating swapfile in '%s' on fstype '%s' using '%s'",
fname, fstype, method)
if method == "fallocate":
- cmd = ['fallocate', '-l', '%dM' % size, fname]
+ cmd = ['fallocate', '-l', '%sM' % size, fname]
elif method == "dd":
cmd = ['dd', 'if=/dev/zero', 'of=%s' % fname, 'bs=1M',
- 'count=%d' % size]
+ 'count=%s' % size]
try:
util.subp(cmd, capture=True)
diff --git a/cloudinit/config/tests/test_mounts.py b/cloudinit/config/tests/test_mounts.py
new file mode 100644
index 0000000..c7dad61
--- /dev/null
+++ b/cloudinit/config/tests/test_mounts.py
@@ -0,0 +1,22 @@
+# This file is part of cloud-init. See LICENSE file for license information.
+from unittest import mock
+
+from cloudinit.config.cc_mounts import create_swapfile
+
+
+M_PATH = 'cloudinit.config.cc_mounts.'
+
+
+class TestCreateSwapfile:
+
+ @mock.patch(M_PATH + 'util.subp')
+ def test_happy_path(self, m_subp, tmpdir):
+ swap_file = tmpdir.join("swap-file")
+ fname = str(swap_file)
+
+ # Some of the calls to util.subp should create the swap file; this
+ # roughly approximates that
+ m_subp.side_effect = lambda *args, **kwargs: swap_file.write('')
+
+ create_swapfile(fname, '')
+ assert mock.call(['mkswap', fname]) in m_subp.call_args_list
--
1.8.3.1

View File

@ -0,0 +1,42 @@
From e7a0cd9aa71dfd7715eca4b393db0aa348e05f8f Mon Sep 17 00:00:00 2001
From: jmaloy <jmaloy@redhat.com>
Date: Thu, 28 May 2020 08:43:58 +0200
Subject: [PATCH 1/4] cc_set_password: increase random pwlength from 9 to 20
(#189)
RH-Author: jmaloy <jmaloy@redhat.com>
Message-id: <20200313015002.3297-2-jmaloy@redhat.com>
Patchwork-id: 94253
O-Subject: [RHEL-8.2 cloud-init PATCH 1/1] cc_set_password: increase random pwlength from 9 to 20 (#189)
Bugzilla: 1812171
RH-Acked-by: Eduardo Otubo <eterrell@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
From: Ryan Harper <ryan.harper@canonical.com>
Increasing the bits of security from 52 to 115.
LP: #1860795
(cherry picked from commit 42788bf24a1a0a5421a2d00a7f59b59e38ba1a14)
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
cloudinit/config/cc_set_passwords.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cloudinit/config/cc_set_passwords.py b/cloudinit/config/cc_set_passwords.py
index c3c5b0f..0742234 100755
--- a/cloudinit/config/cc_set_passwords.py
+++ b/cloudinit/config/cc_set_passwords.py
@@ -236,7 +236,7 @@ def handle(_name, cfg, cloud, log, args):
raise errors[-1]
-def rand_user_password(pwlen=9):
+def rand_user_password(pwlen=20):
return util.rand_str(pwlen, select_from=PW_SET)
--
1.8.3.1

View File

@ -0,0 +1,46 @@
From f67f56e85c0fdb1c94527a6a1795bbacd2e6fdb0 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Wed, 24 Jun 2020 07:34:34 +0200
Subject: [PATCH 4/4] cloud-init.service.tmpl: use "rhel" instead of "redhat"
(#452)
RH-Author: Eduardo Otubo <otubo@redhat.com>
Message-id: <20200623154034.28563-4-otubo@redhat.com>
Patchwork-id: 97784
O-Subject: [RHEL-8.3.0/RHEL-8.2.1 cloud-init PATCH 3/3] cloud-init.service.tmpl: use "rhel" instead of "redhat" (#452)
Bugzilla: 1834173
RH-Acked-by: Cathy Avery <cavery@redhat.com>
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
From: Daniel Watkins <oddbloke@ubuntu.com>
commit ddc4c2de1b1e716b31384af92f5356bfc6136944
Author: Daniel Watkins <oddbloke@ubuntu.com>
Date: Tue Jun 23 09:43:04 2020 -0400
cloud-init.service.tmpl: use "rhel" instead of "redhat" (#452)
We use "rhel" consistently everywhere else.
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
systemd/cloud-init.service.tmpl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/systemd/cloud-init.service.tmpl b/systemd/cloud-init.service.tmpl
index 9ad3574..af6d9a8 100644
--- a/systemd/cloud-init.service.tmpl
+++ b/systemd/cloud-init.service.tmpl
@@ -10,7 +10,7 @@ After=systemd-networkd-wait-online.service
{% if variant in ["ubuntu", "unknown", "debian"] %}
After=networking.service
{% endif %}
-{% if variant in ["centos", "fedora", "redhat"] %}
+{% if variant in ["centos", "fedora", "rhel"] %}
After=network.service
After=NetworkManager.service
{% endif %}
--
1.8.3.1

View File

@ -0,0 +1,350 @@
From f6dc3cf39a4884657478a47894ce8a76ec9a72c5 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Wed, 24 Jun 2020 07:34:29 +0200
Subject: [PATCH 1/4] ec2: Do not log IMDSv2 token values, instead use REDACTED
(#219)
RH-Author: Eduardo Otubo <otubo@redhat.com>
Message-id: <20200505082940.18316-1-otubo@redhat.com>
Patchwork-id: 96264
O-Subject: [RHEL-7.9/RHEL-8.3 cloud-init PATCH] ec2: Do not log IMDSv2 token values, instead use REDACTED (#219)
Bugzilla: 1822343
RH-Acked-by: Cathy Avery <cavery@redhat.com>
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Note: There's no RHEL-8.3/cloud-init-19.4 branch yet, but it should be
queued to be applied on top of it when it's created.
commit 87cd040ed8fe7195cbb357ed3bbf53cd2a81436c
Author: Ryan Harper <ryan.harper@canonical.com>
Date: Wed Feb 19 15:01:09 2020 -0600
ec2: Do not log IMDSv2 token values, instead use REDACTED (#219)
Instead of logging the token values used log the headers and replace the actual
values with the string 'REDACTED'. This allows users to examine cloud-init.log
and see that the IMDSv2 token header is being used but avoids leaving the value
used in the log file itself.
LP: #1863943
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
cloudinit/ec2_utils.py | 12 ++++++++--
cloudinit/sources/DataSourceEc2.py | 35 +++++++++++++++++++----------
cloudinit/url_helper.py | 27 ++++++++++++++++------
tests/unittests/test_datasource/test_ec2.py | 17 ++++++++++++++
4 files changed, 70 insertions(+), 21 deletions(-)
diff --git a/cloudinit/ec2_utils.py b/cloudinit/ec2_utils.py
index 57708c1..34acfe8 100644
--- a/cloudinit/ec2_utils.py
+++ b/cloudinit/ec2_utils.py
@@ -142,7 +142,8 @@ def skip_retry_on_codes(status_codes, _request_args, cause):
def get_instance_userdata(api_version='latest',
metadata_address='http://169.254.169.254',
ssl_details=None, timeout=5, retries=5,
- headers_cb=None, exception_cb=None):
+ headers_cb=None, headers_redact=None,
+ exception_cb=None):
ud_url = url_helper.combine_url(metadata_address, api_version)
ud_url = url_helper.combine_url(ud_url, 'user-data')
user_data = ''
@@ -155,7 +156,8 @@ def get_instance_userdata(api_version='latest',
SKIP_USERDATA_CODES)
response = url_helper.read_file_or_url(
ud_url, ssl_details=ssl_details, timeout=timeout,
- retries=retries, exception_cb=exception_cb, headers_cb=headers_cb)
+ retries=retries, exception_cb=exception_cb, headers_cb=headers_cb,
+ headers_redact=headers_redact)
user_data = response.contents
except url_helper.UrlError as e:
if e.code not in SKIP_USERDATA_CODES:
@@ -169,11 +171,13 @@ def _get_instance_metadata(tree, api_version='latest',
metadata_address='http://169.254.169.254',
ssl_details=None, timeout=5, retries=5,
leaf_decoder=None, headers_cb=None,
+ headers_redact=None,
exception_cb=None):
md_url = url_helper.combine_url(metadata_address, api_version, tree)
caller = functools.partial(
url_helper.read_file_or_url, ssl_details=ssl_details,
timeout=timeout, retries=retries, headers_cb=headers_cb,
+ headers_redact=headers_redact,
exception_cb=exception_cb)
def mcaller(url):
@@ -197,6 +201,7 @@ def get_instance_metadata(api_version='latest',
metadata_address='http://169.254.169.254',
ssl_details=None, timeout=5, retries=5,
leaf_decoder=None, headers_cb=None,
+ headers_redact=None,
exception_cb=None):
# Note, 'meta-data' explicitly has trailing /.
# this is required for CloudStack (LP: #1356855)
@@ -204,6 +209,7 @@ def get_instance_metadata(api_version='latest',
metadata_address=metadata_address,
ssl_details=ssl_details, timeout=timeout,
retries=retries, leaf_decoder=leaf_decoder,
+ headers_redact=headers_redact,
headers_cb=headers_cb,
exception_cb=exception_cb)
@@ -212,12 +218,14 @@ def get_instance_identity(api_version='latest',
metadata_address='http://169.254.169.254',
ssl_details=None, timeout=5, retries=5,
leaf_decoder=None, headers_cb=None,
+ headers_redact=None,
exception_cb=None):
return _get_instance_metadata(tree='dynamic/instance-identity',
api_version=api_version,
metadata_address=metadata_address,
ssl_details=ssl_details, timeout=timeout,
retries=retries, leaf_decoder=leaf_decoder,
+ headers_redact=headers_redact,
headers_cb=headers_cb,
exception_cb=exception_cb)
# vi: ts=4 expandtab
diff --git a/cloudinit/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py
index b9f346a..0f2bfef 100644
--- a/cloudinit/sources/DataSourceEc2.py
+++ b/cloudinit/sources/DataSourceEc2.py
@@ -31,6 +31,9 @@ STRICT_ID_DEFAULT = "warn"
API_TOKEN_ROUTE = 'latest/api/token'
API_TOKEN_DISABLED = '_ec2_disable_api_token'
AWS_TOKEN_TTL_SECONDS = '21600'
+AWS_TOKEN_PUT_HEADER = 'X-aws-ec2-metadata-token'
+AWS_TOKEN_REQ_HEADER = AWS_TOKEN_PUT_HEADER + '-ttl-seconds'
+AWS_TOKEN_REDACT = [AWS_TOKEN_PUT_HEADER, AWS_TOKEN_REQ_HEADER]
class CloudNames(object):
@@ -158,7 +161,8 @@ class DataSourceEc2(sources.DataSource):
for api_ver in self.extended_metadata_versions:
url = url_tmpl.format(self.metadata_address, api_ver)
try:
- resp = uhelp.readurl(url=url, headers=headers)
+ resp = uhelp.readurl(url=url, headers=headers,
+ headers_redact=AWS_TOKEN_REDACT)
except uhelp.UrlError as e:
LOG.debug('url %s raised exception %s', url, e)
else:
@@ -180,6 +184,7 @@ class DataSourceEc2(sources.DataSource):
self.identity = ec2.get_instance_identity(
api_version, self.metadata_address,
headers_cb=self._get_headers,
+ headers_redact=AWS_TOKEN_REDACT,
exception_cb=self._refresh_stale_aws_token_cb).get(
'document', {})
return self.identity.get(
@@ -205,7 +210,8 @@ class DataSourceEc2(sources.DataSource):
LOG.debug('Fetching Ec2 IMDSv2 API Token')
url, response = uhelp.wait_for_url(
urls=urls, max_wait=1, timeout=1, status_cb=self._status_cb,
- headers_cb=self._get_headers, request_method=request_method)
+ headers_cb=self._get_headers, request_method=request_method,
+ headers_redact=AWS_TOKEN_REDACT)
if url and response:
self._api_token = response
@@ -252,7 +258,8 @@ class DataSourceEc2(sources.DataSource):
url, _ = uhelp.wait_for_url(
urls=urls, max_wait=url_params.max_wait_seconds,
timeout=url_params.timeout_seconds, status_cb=LOG.warning,
- headers_cb=self._get_headers, request_method=request_method)
+ headers_redact=AWS_TOKEN_REDACT, headers_cb=self._get_headers,
+ request_method=request_method)
if url:
metadata_address = url2base[url]
@@ -420,6 +427,7 @@ class DataSourceEc2(sources.DataSource):
if not self.wait_for_metadata_service():
return {}
api_version = self.get_metadata_api_version()
+ redact = AWS_TOKEN_REDACT
crawled_metadata = {}
if self.cloud_name == CloudNames.AWS:
exc_cb = self._refresh_stale_aws_token_cb
@@ -429,14 +437,17 @@ class DataSourceEc2(sources.DataSource):
try:
crawled_metadata['user-data'] = ec2.get_instance_userdata(
api_version, self.metadata_address,
- headers_cb=self._get_headers, exception_cb=exc_cb_ud)
+ headers_cb=self._get_headers, headers_redact=redact,
+ exception_cb=exc_cb_ud)
crawled_metadata['meta-data'] = ec2.get_instance_metadata(
api_version, self.metadata_address,
- headers_cb=self._get_headers, exception_cb=exc_cb)
+ headers_cb=self._get_headers, headers_redact=redact,
+ exception_cb=exc_cb)
if self.cloud_name == CloudNames.AWS:
identity = ec2.get_instance_identity(
api_version, self.metadata_address,
- headers_cb=self._get_headers, exception_cb=exc_cb)
+ headers_cb=self._get_headers, headers_redact=redact,
+ exception_cb=exc_cb)
crawled_metadata['dynamic'] = {'instance-identity': identity}
except Exception:
util.logexc(
@@ -455,11 +466,12 @@ class DataSourceEc2(sources.DataSource):
if self.cloud_name != CloudNames.AWS:
return None
LOG.debug("Refreshing Ec2 metadata API token")
- request_header = {'X-aws-ec2-metadata-token-ttl-seconds': seconds}
+ request_header = {AWS_TOKEN_REQ_HEADER: seconds}
token_url = '{}/{}'.format(self.metadata_address, API_TOKEN_ROUTE)
try:
- response = uhelp.readurl(
- token_url, headers=request_header, request_method="PUT")
+ response = uhelp.readurl(token_url, headers=request_header,
+ headers_redact=AWS_TOKEN_REDACT,
+ request_method="PUT")
except uhelp.UrlError as e:
LOG.warning(
'Unable to get API token: %s raised exception %s',
@@ -500,8 +512,7 @@ class DataSourceEc2(sources.DataSource):
API_TOKEN_DISABLED):
return {}
# Request a 6 hour token if URL is API_TOKEN_ROUTE
- request_token_header = {
- 'X-aws-ec2-metadata-token-ttl-seconds': AWS_TOKEN_TTL_SECONDS}
+ request_token_header = {AWS_TOKEN_REQ_HEADER: AWS_TOKEN_TTL_SECONDS}
if API_TOKEN_ROUTE in url:
return request_token_header
if not self._api_token:
@@ -511,7 +522,7 @@ class DataSourceEc2(sources.DataSource):
self._api_token = self._refresh_api_token()
if not self._api_token:
return {}
- return {'X-aws-ec2-metadata-token': self._api_token}
+ return {AWS_TOKEN_PUT_HEADER: self._api_token}
class DataSourceEc2Local(DataSourceEc2):
diff --git a/cloudinit/url_helper.py b/cloudinit/url_helper.py
index 1496a47..3e7de9f 100644
--- a/cloudinit/url_helper.py
+++ b/cloudinit/url_helper.py
@@ -8,6 +8,7 @@
#
# This file is part of cloud-init. See LICENSE file for license information.
+import copy
import json
import os
import requests
@@ -41,6 +42,7 @@ else:
SSL_ENABLED = False
CONFIG_ENABLED = False # This was added in 0.7 (but taken out in >=1.0)
_REQ_VER = None
+REDACTED = 'REDACTED'
try:
from distutils.version import LooseVersion
import pkg_resources
@@ -199,9 +201,9 @@ def _get_ssl_args(url, ssl_details):
def readurl(url, data=None, timeout=None, retries=0, sec_between=1,
- headers=None, headers_cb=None, ssl_details=None,
- check_status=True, allow_redirects=True, exception_cb=None,
- session=None, infinite=False, log_req_resp=True,
+ headers=None, headers_cb=None, headers_redact=None,
+ ssl_details=None, check_status=True, allow_redirects=True,
+ exception_cb=None, session=None, infinite=False, log_req_resp=True,
request_method=None):
"""Wrapper around requests.Session to read the url and retry if necessary
@@ -217,6 +219,7 @@ def readurl(url, data=None, timeout=None, retries=0, sec_between=1,
:param headers: Optional dict of headers to send during request
:param headers_cb: Optional callable returning a dict of values to send as
headers during request
+ :param headers_redact: Optional list of header names to redact from the log
:param ssl_details: Optional dict providing key_file, ca_certs, and
cert_file keys for use on in ssl connections.
:param check_status: Optional boolean set True to raise when HTTPError
@@ -243,6 +246,8 @@ def readurl(url, data=None, timeout=None, retries=0, sec_between=1,
req_args['method'] = request_method
if timeout is not None:
req_args['timeout'] = max(float(timeout), 0)
+ if headers_redact is None:
+ headers_redact = []
# It doesn't seem like config
# was added in older library versions (or newer ones either), thus we
# need to manually do the retries if it wasn't...
@@ -287,6 +292,12 @@ def readurl(url, data=None, timeout=None, retries=0, sec_between=1,
if k == 'data':
continue
filtered_req_args[k] = v
+ if k == 'headers':
+ for hkey, _hval in v.items():
+ if hkey in headers_redact:
+ filtered_req_args[k][hkey] = (
+ copy.deepcopy(req_args[k][hkey]))
+ filtered_req_args[k][hkey] = REDACTED
try:
if log_req_resp:
@@ -339,8 +350,8 @@ def readurl(url, data=None, timeout=None, retries=0, sec_between=1,
return None # Should throw before this...
-def wait_for_url(urls, max_wait=None, timeout=None,
- status_cb=None, headers_cb=None, sleep_time=1,
+def wait_for_url(urls, max_wait=None, timeout=None, status_cb=None,
+ headers_cb=None, headers_redact=None, sleep_time=1,
exception_cb=None, sleep_time_cb=None, request_method=None):
"""
urls: a list of urls to try
@@ -352,6 +363,7 @@ def wait_for_url(urls, max_wait=None, timeout=None,
status_cb: call method with string message when a url is not available
headers_cb: call method with single argument of url to get headers
for request.
+ headers_redact: a list of header names to redact from the log
exception_cb: call method with 2 arguments 'msg' (per status_cb) and
'exception', the exception that occurred.
sleep_time_cb: call method with 2 arguments (response, loop_n) that
@@ -415,8 +427,9 @@ def wait_for_url(urls, max_wait=None, timeout=None,
headers = {}
response = readurl(
- url, headers=headers, timeout=timeout,
- check_status=False, request_method=request_method)
+ url, headers=headers, headers_redact=headers_redact,
+ timeout=timeout, check_status=False,
+ request_method=request_method)
if not response.contents:
reason = "empty response [%s]" % (response.code)
url_exc = UrlError(ValueError(reason), code=response.code,
diff --git a/tests/unittests/test_datasource/test_ec2.py b/tests/unittests/test_datasource/test_ec2.py
index 34a089f..bd5bd4c 100644
--- a/tests/unittests/test_datasource/test_ec2.py
+++ b/tests/unittests/test_datasource/test_ec2.py
@@ -429,6 +429,23 @@ class TestEc2(test_helpers.HttprettyTestCase):
self.assertTrue(ds.get_data())
self.assertFalse(ds.is_classic_instance())
+ def test_aws_token_redacted(self):
+ """Verify that aws tokens are redacted when logged."""
+ ds = self._setup_ds(
+ platform_data=self.valid_platform_data,
+ sys_cfg={'datasource': {'Ec2': {'strict_id': False}}},
+ md={'md': DEFAULT_METADATA})
+ self.assertTrue(ds.get_data())
+ all_logs = self.logs.getvalue().splitlines()
+ REDACT_TTL = "'X-aws-ec2-metadata-token-ttl-seconds': 'REDACTED'"
+ REDACT_TOK = "'X-aws-ec2-metadata-token': 'REDACTED'"
+ logs_with_redacted_ttl = [log for log in all_logs if REDACT_TTL in log]
+ 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(79, len(logs_with_redacted))
+ self.assertEqual(0, len(logs_with_token))
+
@mock.patch('cloudinit.net.dhcp.maybe_perform_dhcp_discovery')
def test_valid_platform_with_strict_true(self, m_dhcp):
"""Valid platform data should return true with strict_id true."""
--
1.8.3.1

View File

@ -0,0 +1,128 @@
From dc9460f161efce6770f66bb95d60cea6d27df722 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Thu, 25 Jun 2020 08:03:59 +0200
Subject: [PATCH] ec2: only redact token request headers in logs, avoid
altering request (#230)
RH-Author: Eduardo Otubo <otubo@redhat.com>
Message-id: <20200624112104.376-1-otubo@redhat.com>
Patchwork-id: 97793
O-Subject: [RHEL-8.3.0 cloud-init PATCH] ec2: only redact token request headers in logs, avoid altering request (#230)
Bugzilla: 1822343
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
RH-Acked-by: Cathy Avery <cavery@redhat.com>
From: Chad Smith <chad.smith@canonical.com>
commit fa1abfec27050a4fb71cad950a17e42f9b43b478
Author: Chad Smith <chad.smith@canonical.com>
Date: Tue Mar 3 15:23:33 2020 -0700
ec2: only redact token request headers in logs, avoid altering request (#230)
Our header redact logic was redacting both logged request headers and
the actual source request. This results in DataSourceEc2 sending the
invalid header "X-aws-ec2-metadata-token-ttl-seconds: REDACTED" which
gets an HTTP status response of 400.
Cloud-init retries this failed token request for 2 minutes before
falling back to IMDSv1.
LP: #1865882
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
cloudinit/tests/test_url_helper.py | 34 +++++++++++++++++++++++++++++++++-
cloudinit/url_helper.py | 15 ++++++++-------
2 files changed, 41 insertions(+), 8 deletions(-)
diff --git a/cloudinit/tests/test_url_helper.py b/cloudinit/tests/test_url_helper.py
index 1674120..29b3937 100644
--- a/cloudinit/tests/test_url_helper.py
+++ b/cloudinit/tests/test_url_helper.py
@@ -1,7 +1,8 @@
# This file is part of cloud-init. See LICENSE file for license information.
from cloudinit.url_helper import (
- NOT_FOUND, UrlError, oauth_headers, read_file_or_url, retry_on_url_exc)
+ NOT_FOUND, UrlError, REDACTED, oauth_headers, read_file_or_url,
+ retry_on_url_exc)
from cloudinit.tests.helpers import CiTestCase, mock, skipIf
from cloudinit import util
from cloudinit import version
@@ -50,6 +51,9 @@ class TestOAuthHeaders(CiTestCase):
class TestReadFileOrUrl(CiTestCase):
+
+ with_logs = True
+
def test_read_file_or_url_str_from_file(self):
"""Test that str(result.contents) on file is text version of contents.
It should not be "b'data'", but just "'data'" """
@@ -71,6 +75,34 @@ class TestReadFileOrUrl(CiTestCase):
self.assertEqual(result.contents, data)
self.assertEqual(str(result), data.decode('utf-8'))
+ @httpretty.activate
+ def test_read_file_or_url_str_from_url_redacting_headers_from_logs(self):
+ """Headers are redacted from logs but unredacted in requests."""
+ url = 'http://hostname/path'
+ headers = {'sensitive': 'sekret', 'server': 'blah'}
+ httpretty.register_uri(httpretty.GET, url)
+
+ read_file_or_url(url, headers=headers, headers_redact=['sensitive'])
+ logs = self.logs.getvalue()
+ for k in headers.keys():
+ self.assertEqual(headers[k], httpretty.last_request().headers[k])
+ self.assertIn(REDACTED, logs)
+ self.assertNotIn('sekret', logs)
+
+ @httpretty.activate
+ def test_read_file_or_url_str_from_url_redacts_noheaders(self):
+ """When no headers_redact, header values are in logs and requests."""
+ url = 'http://hostname/path'
+ headers = {'sensitive': 'sekret', 'server': 'blah'}
+ httpretty.register_uri(httpretty.GET, url)
+
+ read_file_or_url(url, headers=headers)
+ for k in headers.keys():
+ self.assertEqual(headers[k], httpretty.last_request().headers[k])
+ logs = self.logs.getvalue()
+ self.assertNotIn(REDACTED, logs)
+ self.assertIn('sekret', logs)
+
@mock.patch(M_PATH + 'readurl')
def test_read_file_or_url_passes_params_to_readurl(self, m_readurl):
"""read_file_or_url passes all params through to readurl."""
diff --git a/cloudinit/url_helper.py b/cloudinit/url_helper.py
index 3e7de9f..e6188ea 100644
--- a/cloudinit/url_helper.py
+++ b/cloudinit/url_helper.py
@@ -291,13 +291,14 @@ def readurl(url, data=None, timeout=None, retries=0, sec_between=1,
for (k, v) in req_args.items():
if k == 'data':
continue
- filtered_req_args[k] = v
- if k == 'headers':
- for hkey, _hval in v.items():
- if hkey in headers_redact:
- filtered_req_args[k][hkey] = (
- copy.deepcopy(req_args[k][hkey]))
- filtered_req_args[k][hkey] = REDACTED
+ if k == 'headers' and headers_redact:
+ matched_headers = [k for k in headers_redact if v.get(k)]
+ if matched_headers:
+ filtered_req_args[k] = copy.deepcopy(v)
+ for key in matched_headers:
+ filtered_req_args[k][key] = REDACTED
+ else:
+ filtered_req_args[k] = v
try:
if log_req_resp:
--
1.8.3.1

View File

@ -0,0 +1,203 @@
From 3ee8f2f5dde1bb27e682c5985bffe6fb9f9e5e0b Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Thu, 5 Nov 2020 12:42:26 +0100
Subject: [PATCH 5/5] net: fix rendering of 'static6' in network config (#77)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Eduardo Terrell Ferrari Otubo (eterrell)
RH-MergeRequest: 17: Explicit set IPV6_AUTOCONF and IPV6_FORCE_ACCEPT_RA on static6 (#634)
RH-Commit: [2/2] 30eb756aceb37761d50c70eb4f684662a11afa3f (eterrell/cloud-init)
RH-Bugzilla: 1894015
commit dacdd30080bd8183d1f1c1dc9dbcbc8448301529
Author: Ryan Harper <ryan.harper@canonical.com>
Date: Wed Jan 8 11:30:17 2020 -0600
net: fix rendering of 'static6' in network config (#77)
* net: fix rendering of 'static6' in network config
A V1 static6 network typo was misrendered in eni, it's not valid.
It was ignored in sysconfig and netplan. This branch fixes eni,
updates sysconfig, netplan to render it correctly and adds unittests
for all cases.
Reported-by: Raphaël Enrici
LP: #1850988
* net: add comment about static6 type in subnet_is_ipv6
Co-authored-by: Chad Smith <blackboxsw@gmail.com>
Co-authored-by: Daniel Watkins <daniel@daniel-watkins.co.uk>
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
---
cloudinit/net/eni.py | 4 +-
cloudinit/net/netplan.py | 2 +-
cloudinit/net/network_state.py | 2 +-
cloudinit/net/sysconfig.py | 4 +-
tests/unittests/test_distros/test_netconfig.py | 55 +++++++++++++++++++++++++-
5 files changed, 61 insertions(+), 6 deletions(-)
diff --git a/cloudinit/net/eni.py b/cloudinit/net/eni.py
index 7077106..2f71456 100644
--- a/cloudinit/net/eni.py
+++ b/cloudinit/net/eni.py
@@ -429,7 +429,9 @@ class Renderer(renderer.Renderer):
iface['mode'] = 'auto'
# Use stateless DHCPv6 (0=off, 1=on)
iface['dhcp'] = '0'
- elif subnet_is_ipv6(subnet) and subnet['type'] == 'static':
+ elif subnet_is_ipv6(subnet):
+ # mode might be static6, eni uses 'static'
+ iface['mode'] = 'static'
if accept_ra is not None:
# Accept router advertisements (0=off, 1=on)
iface['accept_ra'] = '1' if accept_ra else '0'
diff --git a/cloudinit/net/netplan.py b/cloudinit/net/netplan.py
index 14d3999..8985527 100644
--- a/cloudinit/net/netplan.py
+++ b/cloudinit/net/netplan.py
@@ -98,7 +98,7 @@ def _extract_addresses(config, entry, ifname, features=None):
entry.update({sn_type: True})
elif sn_type in IPV6_DYNAMIC_TYPES:
entry.update({'dhcp6': True})
- elif sn_type in ['static']:
+ elif sn_type in ['static', 'static6']:
addr = "%s" % subnet.get('address')
if 'prefix' in subnet:
addr += "/%d" % subnet.get('prefix')
diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py
index 2525fc9..48e5b6e 100644
--- a/cloudinit/net/network_state.py
+++ b/cloudinit/net/network_state.py
@@ -942,7 +942,7 @@ def subnet_is_ipv6(subnet):
# 'static6', 'dhcp6', 'ipv6_dhcpv6-stateful', 'ipv6_dhcpv6-stateless' or
# 'ipv6_slaac'
if subnet['type'].endswith('6') or subnet['type'] in IPV6_DYNAMIC_TYPES:
- # This is a request for DHCPv6.
+ # This is a request either static6 type or DHCPv6.
return True
elif subnet['type'] == 'static' and is_ipv6_addr(subnet.get('address')):
return True
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index 4210544..1989d01 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -378,7 +378,7 @@ class Renderer(renderer.Renderer):
iface_cfg['IPV6_AUTOCONF'] = True
elif subnet_type in ['dhcp4', 'dhcp']:
iface_cfg['BOOTPROTO'] = 'dhcp'
- elif subnet_type == 'static':
+ elif subnet_type in ['static', 'static6']:
# grep BOOTPROTO sysconfig.txt -A2 | head -3
# BOOTPROTO=none|bootp|dhcp
# 'bootp' or 'dhcp' cause a DHCP client
@@ -434,7 +434,7 @@ class Renderer(renderer.Renderer):
continue
elif subnet_type in IPV6_DYNAMIC_TYPES:
continue
- elif subnet_type == 'static':
+ elif subnet_type in ['static', 'static6']:
if subnet_is_ipv6(subnet):
ipv6_index = ipv6_index + 1
ipv6_cidr = "%s/%s" % (subnet['address'], subnet['prefix'])
diff --git a/tests/unittests/test_distros/test_netconfig.py b/tests/unittests/test_distros/test_netconfig.py
index b85a333..e277bca 100644
--- a/tests/unittests/test_distros/test_netconfig.py
+++ b/tests/unittests/test_distros/test_netconfig.py
@@ -109,13 +109,31 @@ auto eth1
iface eth1 inet dhcp
"""
+V1_NET_CFG_IPV6_OUTPUT = """\
+# This file is generated from information provided by the datasource. Changes
+# to it will not persist across an instance reboot. To disable cloud-init's
+# network configuration capabilities, write a file
+# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
+# network: {config: disabled}
+auto lo
+iface lo inet loopback
+
+auto eth0
+iface eth0 inet6 static
+ address 2607:f0d0:1002:0011::2/64
+ gateway 2607:f0d0:1002:0011::1
+
+auto eth1
+iface eth1 inet dhcp
+"""
+
V1_NET_CFG_IPV6 = {'config': [{'name': 'eth0',
'subnets': [{'address':
'2607:f0d0:1002:0011::2',
'gateway':
'2607:f0d0:1002:0011::1',
'netmask': '64',
- 'type': 'static'}],
+ 'type': 'static6'}],
'type': 'physical'},
{'name': 'eth1',
'subnets': [{'control': 'auto',
@@ -141,6 +159,23 @@ network:
dhcp4: true
"""
+V1_TO_V2_NET_CFG_IPV6_OUTPUT = """\
+# This file is generated from information provided by the datasource. Changes
+# to it will not persist across an instance reboot. To disable cloud-init's
+# network configuration capabilities, write a file
+# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
+# network: {config: disabled}
+network:
+ version: 2
+ ethernets:
+ eth0:
+ addresses:
+ - 2607:f0d0:1002:0011::2/64
+ gateway6: 2607:f0d0:1002:0011::1
+ eth1:
+ dhcp4: true
+"""
+
V2_NET_CFG = {
'ethernets': {
'eth7': {
@@ -376,6 +411,14 @@ class TestNetCfgDistroUbuntuEni(TestNetCfgDistroBase):
V1_NET_CFG,
expected_cfgs=expected_cfgs.copy())
+ def test_apply_network_config_ipv6_ub(self):
+ expected_cfgs = {
+ self.eni_path(): V1_NET_CFG_IPV6_OUTPUT
+ }
+ self._apply_and_verify_eni(self.distro.apply_network_config,
+ V1_NET_CFG_IPV6,
+ expected_cfgs=expected_cfgs.copy())
+
class TestNetCfgDistroUbuntuNetplan(TestNetCfgDistroBase):
def setUp(self):
@@ -419,6 +462,16 @@ class TestNetCfgDistroUbuntuNetplan(TestNetCfgDistroBase):
V1_NET_CFG,
expected_cfgs=expected_cfgs.copy())
+ def test_apply_network_config_v1_ipv6_to_netplan_ub(self):
+ expected_cfgs = {
+ self.netplan_path(): V1_TO_V2_NET_CFG_IPV6_OUTPUT,
+ }
+
+ # ub_distro.apply_network_config(V1_NET_CFG_IPV6, False)
+ self._apply_and_verify_netplan(self.distro.apply_network_config,
+ V1_NET_CFG_IPV6,
+ expected_cfgs=expected_cfgs.copy())
+
def test_apply_network_config_v2_passthrough_ub(self):
expected_cfgs = {
self.netplan_path(): V2_TO_V2_NET_CFG_OUTPUT,
--
1.8.3.1

View File

@ -0,0 +1,254 @@
From 2f9d58439c94fe00cee951c213f14ace6da73691 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Tue, 15 Sep 2020 18:00:00 +0200
Subject: [PATCH 2/5] network: Fix type and respect name when rendering vlan in
sysconfig. (#541)
RH-Author: Eduardo Terrell Ferrari Otubo (eterrell)
RH-MergeRequest: 10: ifup bond0.504 Error: Connection activation failed: No suitable device found for this connection [rhel-8.3.0.z]
RH-Commit: [1/1] fe8bd8bc184d2391b3f9ac6af80e231649d6019a (eterrell/cloud-init)
RH-Bugzilla: 1890551
commit 8439b191ec2f336d544cab86dba2860f969cd5b8
Author: Eduardo Otubo <otubo@redhat.com>
Date: Tue Sep 15 18:00:00 2020 +0200
network: Fix type and respect name when rendering vlan in sysconfig. (#541)
Prior to this change, vlans were rendered in sysconfig with
'TYPE=Ethernet', and incorrectly rendered the PHYSDEV based on
the name of the vlan device rather than the 'link' provided
in the network config.
The change here fixes:
* rendering of TYPE=Ethernet for a vlan
* adds a warning if the configured device name is not supported
per the RHEL 7 docs "11.5. Naming Scheme for VLAN Interfaces"
LP: #1788915
LP: #1826608
RHBZ: #1861871
Conflicts:
* A hunk on cloudinit/net/sysconfig.py could not apply cleanly as it
depends on a verification on the distro flavor, which is not implemented
on cloud-init-19.4.
* Couple of hunks could not apply cleanly on tests/unittests/test_net.py
because the definition of unit test response moved a little bit.
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
---
cloudinit/net/sysconfig.py | 32 +++++++++-
tests/unittests/test_distros/test_netconfig.py | 81 ++++++++++++++++++++++++++
tests/unittests/test_net.py | 4 --
3 files changed, 112 insertions(+), 5 deletions(-)
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index 810b283..4b4ed09 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -95,6 +95,10 @@ class ConfigMap(object):
def __len__(self):
return len(self._conf)
+ def skip_key_value(self, key, val):
+ """Skip the pair key, value if it matches a certain rule."""
+ return False
+
def to_string(self):
buf = six.StringIO()
buf.write(_make_header())
@@ -102,6 +106,8 @@ class ConfigMap(object):
buf.write("\n")
for key in sorted(self._conf.keys()):
value = self._conf[key]
+ if self.skip_key_value(key, value):
+ continue
if isinstance(value, bool):
value = self._bool_map[value]
if not isinstance(value, six.string_types):
@@ -207,6 +213,7 @@ class NetInterface(ConfigMap):
'bond': 'Bond',
'bridge': 'Bridge',
'infiniband': 'InfiniBand',
+ 'vlan': 'Vlan',
}
def __init__(self, iface_name, base_sysconf_dir, templates,
@@ -260,6 +267,11 @@ class NetInterface(ConfigMap):
c.routes = self.routes.copy()
return c
+ def skip_key_value(self, key, val):
+ if key == 'TYPE' and val == 'Vlan':
+ return True
+ return False
+
class Renderer(renderer.Renderer):
"""Renders network information in a /etc/sysconfig format."""
@@ -599,7 +611,16 @@ class Renderer(renderer.Renderer):
iface_name = iface['name']
iface_cfg = iface_contents[iface_name]
iface_cfg['VLAN'] = True
- iface_cfg['PHYSDEV'] = iface_name[:iface_name.rfind('.')]
+ iface_cfg.kind = 'vlan'
+
+ rdev = iface['vlan-raw-device']
+ supported = _supported_vlan_names(rdev, iface['vlan_id'])
+ if iface_name not in supported:
+ LOG.info(
+ "Name '%s' for vlan '%s' is not officially supported"
+ "by RHEL. Supported: %s",
+ iface_name, rdev, ' '.join(supported))
+ iface_cfg['PHYSDEV'] = rdev
iface_subnets = iface.get("subnets", [])
route_cfg = iface_cfg.routes
@@ -771,6 +792,15 @@ class Renderer(renderer.Renderer):
"\n".join(netcfg) + "\n", file_mode)
+def _supported_vlan_names(rdev, vid):
+ """Return list of supported names for vlan devices per RHEL doc
+ 11.5. Naming Scheme for VLAN Interfaces."""
+ return [
+ v.format(rdev=rdev, vid=int(vid))
+ for v in ("{rdev}{vid:04}", "{rdev}{vid}",
+ "{rdev}.{vid:04}", "{rdev}.{vid}")]
+
+
def available(target=None):
sysconfig = available_sysconfig(target=target)
nm = available_nm(target=target)
diff --git a/tests/unittests/test_distros/test_netconfig.py b/tests/unittests/test_distros/test_netconfig.py
index 6720995..4ea4203 100644
--- a/tests/unittests/test_distros/test_netconfig.py
+++ b/tests/unittests/test_distros/test_netconfig.py
@@ -526,6 +526,87 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase):
V1_NET_CFG_IPV6,
expected_cfgs=expected_cfgs.copy())
+ def test_vlan_render_unsupported(self):
+ """Render officially unsupported vlan names."""
+ cfg = {
+ 'version': 2,
+ 'ethernets': {
+ 'eth0': {'addresses': ["192.10.1.2/24"],
+ 'match': {'macaddress': "00:16:3e:60:7c:df"}}},
+ 'vlans': {
+ 'infra0': {'addresses': ["10.0.1.2/16"],
+ 'id': 1001, 'link': 'eth0'}},
+ }
+ expected_cfgs = {
+ self.ifcfg_path('eth0'): dedent("""\
+ BOOTPROTO=none
+ DEVICE=eth0
+ 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
+ """),
+ self.ifcfg_path('infra0'): dedent("""\
+ BOOTPROTO=none
+ DEVICE=infra0
+ IPADDR=10.0.1.2
+ NETMASK=255.255.0.0
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ PHYSDEV=eth0
+ USERCTL=no
+ VLAN=yes
+ """),
+ self.control_path(): dedent("""\
+ NETWORKING=yes
+ """),
+ }
+ self._apply_and_verify(
+ self.distro.apply_network_config, cfg,
+ expected_cfgs=expected_cfgs)
+
+ def test_vlan_render(self):
+ cfg = {
+ 'version': 2,
+ 'ethernets': {
+ 'eth0': {'addresses': ["192.10.1.2/24"]}},
+ 'vlans': {
+ 'eth0.1001': {'addresses': ["10.0.1.2/16"],
+ 'id': 1001, 'link': 'eth0'}},
+ }
+ expected_cfgs = {
+ self.ifcfg_path('eth0'): dedent("""\
+ BOOTPROTO=none
+ DEVICE=eth0
+ IPADDR=192.10.1.2
+ NETMASK=255.255.255.0
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ TYPE=Ethernet
+ USERCTL=no
+ """),
+ self.ifcfg_path('eth0.1001'): dedent("""\
+ BOOTPROTO=none
+ DEVICE=eth0.1001
+ IPADDR=10.0.1.2
+ NETMASK=255.255.0.0
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ PHYSDEV=eth0
+ USERCTL=no
+ VLAN=yes
+ """),
+ self.control_path(): dedent("""\
+ NETWORKING=yes
+ """),
+ }
+ self._apply_and_verify(
+ self.distro.apply_network_config, cfg,
+ expected_cfgs=expected_cfgs)
+
class TestNetCfgDistroOpensuse(TestNetCfgDistroBase):
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index a931a3e..2eedb12 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -1496,7 +1496,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true
ONBOOT=yes
PHYSDEV=bond0
STARTMODE=auto
- TYPE=Ethernet
USERCTL=no
VLAN=yes"""),
'ifcfg-br0': textwrap.dedent("""\
@@ -1541,7 +1540,6 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true
ONBOOT=yes
PHYSDEV=eth0
STARTMODE=auto
- TYPE=Ethernet
USERCTL=no
VLAN=yes"""),
'ifcfg-eth1': textwrap.dedent("""\
@@ -2163,7 +2161,6 @@ iface bond0 inet6 static
ONBOOT=yes
PHYSDEV=en0
STARTMODE=auto
- TYPE=Ethernet
USERCTL=no
VLAN=yes"""),
},
@@ -3180,7 +3177,6 @@ USERCTL=no
ONBOOT=yes
PHYSDEV=eno1
STARTMODE=auto
- TYPE=Ethernet
USERCTL=no
VLAN=yes
""")
--
1.8.3.1

View File

@ -0,0 +1,74 @@
From 44b6004ee17cd2ae5930c7d8fd3ecafd7485a4d6 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Mon, 17 Aug 2020 11:14:47 +0200
Subject: [PATCH 2/2] ssh exit with non-zero status on disabled user (#472)
RH-Author: Eduardo Otubo <otubo@redhat.com>
Message-id: <20200729074459.16096-1-otubo@redhat.com>
Patchwork-id: 98071
O-Subject: [RHEL-8.3.0 cloud-init PATCH] ssh exit with non-zero status on disabled user (#472)
Bugzilla: 1833874
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
commit e161059a18173e2b61c54dba9eab774401fb5f1f
Author: Eduardo Otubo <otubo@redhat.com>
Date: Wed Jul 15 20:21:02 2020 +0200
ssh exit with non-zero status on disabled user (#472)
It is confusing for scripts, where a disabled user has been specified,
that ssh exits with a zero status by default without indication anything
failed.
I think exitting with a non-zero status would make more clear in scripts
and automated setups where things failed, thus making noticing the issue
and debugging easier.
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Signed-off-by: Aleksandar Kostadinov <akostadi@redhat.com>
LP: #1170059
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
cloudinit/ssh_util.py | 4 +++-
doc/examples/cloud-config.txt | 2 +-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/cloudinit/ssh_util.py b/cloudinit/ssh_util.py
index bcb23a5..8ff61a2 100644
--- a/cloudinit/ssh_util.py
+++ b/cloudinit/ssh_util.py
@@ -40,11 +40,13 @@ VALID_KEY_TYPES = (
"ssh-rsa-cert-v01@openssh.com",
)
+_DISABLE_USER_SSH_EXIT = 142
DISABLE_USER_OPTS = (
"no-port-forwarding,no-agent-forwarding,"
"no-X11-forwarding,command=\"echo \'Please login as the user \\\"$USER\\\""
- " rather than the user \\\"$DISABLE_USER\\\".\';echo;sleep 10\"")
+ " rather than the user \\\"$DISABLE_USER\\\".\';echo;sleep 10;"
+ "exit " + str(_DISABLE_USER_SSH_EXIT) + "\"")
class AuthKeyLine(object):
diff --git a/doc/examples/cloud-config.txt b/doc/examples/cloud-config.txt
index 0e82b83..f00db68 100644
--- a/doc/examples/cloud-config.txt
+++ b/doc/examples/cloud-config.txt
@@ -235,7 +235,7 @@ disable_root: false
# The string '$USER' will be replaced with the username of the default user.
# The string '$DISABLE_USER' will be replaced with the username to disable.
#
-# disable_root_opts: no-port-forwarding,no-agent-forwarding,no-X11-forwarding,command="echo 'Please login as the user \"$USER\" rather than the user \"$DISABLE_USER\".';echo;sleep 10"
+# disable_root_opts: no-port-forwarding,no-agent-forwarding,no-X11-forwarding,command="echo 'Please login as the user \"$USER\" rather than the user \"$DISABLE_USER\".';echo;sleep 10;exit 142"
# disable ssh access for non-root-users
# To disable ssh access for non-root users, ssh_redirect_user: true can be
--
1.8.3.1

View File

@ -0,0 +1,55 @@
From 4f177d3363a0efb2ee67b8a46efaca7707c2437f Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Mon, 24 Aug 2020 15:25:36 +0200
Subject: [PATCH 2/3] swap file "size" being used before checked if str (#315)
RH-Author: Eduardo Otubo <otubo@redhat.com>
Message-id: <20200820092042.5418-3-otubo@redhat.com>
Patchwork-id: 98192
O-Subject: [RHEL-8.3.0 cloud-init PATCH 2/3] swap file "size" being used before checked if str (#315)
Bugzilla: 1794664
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
commit 46cf23c28812d3e3ba0c570defd9a05628af5556
Author: Eduardo Otubo <otubo@redhat.com>
Date: Tue Apr 14 17:45:14 2020 +0200
swap file "size" being used before checked if str
Swap file size variable was being used before checked if it's set to str
"auto". If set to "auto", it will break with:
failed to setup swap: unsupported operand type(s) for /: 'str' and 'int'
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
cloudinit/config/cc_mounts.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cloudinit/config/cc_mounts.py b/cloudinit/config/cc_mounts.py
index 4293844..0573026 100644
--- a/cloudinit/config/cc_mounts.py
+++ b/cloudinit/config/cc_mounts.py
@@ -274,7 +274,6 @@ def setup_swapfile(fname, size=None, maxsize=None):
maxsize: the maximum size
"""
swap_dir = os.path.dirname(fname)
- mibsize = str(int(size / (2 ** 20)))
if str(size).lower() == "auto":
try:
memsize = util.read_meminfo()['total']
@@ -286,6 +285,7 @@ def setup_swapfile(fname, size=None, maxsize=None):
size = suggested_swapsize(fsys=swap_dir, maxsize=maxsize,
memsize=memsize)
+ mibsize = str(int(size / (2 ** 20)))
if not size:
LOG.debug("Not creating swap: suggested size was 0")
return
--
1.8.3.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,46 @@
From ebbc83c1ca52620179d94dc1d92c44883273e4ef Mon Sep 17 00:00:00 2001
From: jmaloy <jmaloy@redhat.com>
Date: Thu, 28 May 2020 08:44:02 +0200
Subject: [PATCH 2/4] utils: use SystemRandom when generating random password.
(#204)
RH-Author: jmaloy <jmaloy@redhat.com>
Message-id: <20200313184329.16696-2-jmaloy@redhat.com>
Patchwork-id: 94294
O-Subject: [RHEL-8.2 cloud-init PATCH 1/1] utils: use SystemRandom when generating random password. (#204)
Bugzilla: 1812174
RH-Acked-by: Eduardo Otubo <eterrell@redhat.com>
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
From: Dimitri John Ledkov <xnox@ubuntu.com>
As noticed by Seth Arnold, non-deterministic SystemRandom should be
used when creating security sensitive random strings.
(cherry picked from commit 3e2f7356effc9e9cccc5ae945846279804eedc46)
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
cloudinit/util.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/cloudinit/util.py b/cloudinit/util.py
index 9d9d5c7..5d51ba8 100644
--- a/cloudinit/util.py
+++ b/cloudinit/util.py
@@ -401,9 +401,10 @@ def translate_bool(val, addons=None):
def rand_str(strlen=32, select_from=None):
+ r = random.SystemRandom()
if not select_from:
select_from = string.ascii_letters + string.digits
- return "".join([random.choice(select_from) for _x in range(0, strlen)])
+ return "".join([r.choice(select_from) for _x in range(0, strlen)])
def rand_dict_key(dictionary, postfix=None):
--
1.8.3.1

View File

@ -0,0 +1 @@
d /run/cloud-init 0700 root root - -

589
SPECS/cloud-init.spec Normal file
View File

@ -0,0 +1,589 @@
%{!?license: %global license %%doc}
# The only reason we are archful is because dmidecode is ExclusiveArch
# https://bugzilla.redhat.com/show_bug.cgi?id=1067089
%global debug_package %{nil}
Name: cloud-init
Version: 19.4
Release: 11%{?dist}.3
Summary: Cloud instance init scripts
Group: System Environment/Base
License: GPLv3
URL: http://launchpad.net/cloud-init
Source0: https://launchpad.net/cloud-init/trunk/%{version}/+download/%{name}-%{version}.tar.gz
Source1: cloud-init-tmpfiles.conf
Patch0001: 0001-Add-initial-redhat-setup.patch
Patch0002: 0002-Do-not-write-NM_CONTROLLED-no-in-generated-interface.patch
Patch0003: 0003-limit-permissions-on-def_log_file.patch
Patch0004: 0004-sysconfig-Don-t-write-BOOTPROTO-dhcp-for-ipv6-dhcp.patch
Patch0005: 0005-DataSourceAzure.py-use-hostnamectl-to-set-hostname.patch
Patch0006: 0006-include-NOZEROCONF-yes-in-etc-sysconfig-network.patch
Patch0007: 0007-Remove-race-condition-between-cloud-init-and-Network.patch
# For bz#1812171 - CVE-2020-8632 cloud-init: Too short random password length in cc_set_password in config/cc_set_passwords.py [rhel-8]
Patch8: ci-cc_set_password-increase-random-pwlength-from-9-to-2.patch
# For bz#1812174 - CVE-2020-8631 cloud-init: Use of random.choice when generating random password [rhel-8]
Patch9: ci-utils-use-SystemRandom-when-generating-random-passwo.patch
# For bz#1814152 - CVE-2018-10896 cloud-init: default configuration disabled deletion of SSH host keys [rhel-8]
Patch10: ci-Enable-ssh_deletekeys-by-default.patch
# For bz#1840648 - [cloud-init][RHEL-8.2.0] /etc/resolv.conf lose config after reboot (initial instance is ok)
Patch11: ci-Remove-race-condition-between-cloud-init-and-Network.patch
# For bz#1803928 - [RHEL8.3] Race condition of starting cloud-init and NetworkManager
Patch12: ci-Make-cloud-init.service-execute-after-network-is-up.patch
# For bz#1822343 - [RHEL8.3] Do not log IMDSv2 token values into cloud-init.log
Patch13: ci-ec2-Do-not-log-IMDSv2-token-values-instead-use-REDAC.patch
# For bz#1834173 - [rhel-8.3]Incorrect ds-identify check in cloud-init-generator
Patch14: ci-Change-from-redhat-to-rhel-in-systemd-generator-tmpl.patch
# For bz#1834173 - [rhel-8.3]Incorrect ds-identify check in cloud-init-generator
Patch15: ci-cloud-init.service.tmpl-use-rhel-instead-of-redhat-4.patch
# For bz#1822343 - [RHEL8.3] Do not log IMDSv2 token values into cloud-init.log
Patch16: ci-ec2-only-redact-token-request-headers-in-logs-avoid-.patch
# For bz#1839662 - [ESXi][RHEL8.3][cloud-init]ERROR log in cloud-init.log after clone VM on ESXi platform
Patch17: ci-When-tools.conf-does-not-exist-running-cmd-vmware-to.patch
# For bz#1833874 - [rhel-8.3]using root user error should cause a non-zero exit code
Patch18: ci-ssh-exit-with-non-zero-status-on-disabled-user-472.patch
# For bz#1794664 - [RHEL8] swapon fails with "swapfile has holes" when created on a xfs filesystem by cloud-init
Patch19: ci-Do-not-use-fallocate-in-swap-file-creation-on-xfs.-7.patch
# For bz#1794664 - [RHEL8] swapon fails with "swapfile has holes" when created on a xfs filesystem by cloud-init
Patch20: ci-swap-file-size-being-used-before-checked-if-str-315.patch
# For bz#1794664 - [RHEL8] swapon fails with "swapfile has holes" when created on a xfs filesystem by cloud-init
Patch21: ci-Detect-kernel-version-before-swap-file-creation-428.patch
# For bz#1839662 - [ESXi][RHEL8.3][cloud-init]ERROR log in cloud-init.log after clone VM on ESXi platform
Patch22: ci-Changing-notation-of-subp-call.patch
# For bz#1794664 - [RHEL8] swapon fails with "swapfile has holes" when created on a xfs filesystem by cloud-init
Patch23: ci-cc_mounts-fix-incorrect-format-specifiers-316.patch
# For bz#1879989 - [Azure][RHEL 8] cloud-init Permission denied with the use of mount option noexec [rhel-8.3.0.z]
Patch24: ci-DHCP-sandboxing-failing-on-noexec-mounted-var-tmp-52.patch
# For bz#1890551 - [rhel8][cloud-init] ifup bond0.504 Error: Connection activation failed: No suitable device found for this connection [rhel-8.3.0.z]
Patch25: ci-network-Fix-type-and-respect-name-when-rendering-vla.patch
# For bz#1894014 - Support for cloud-init config modules for PowerVM Hypervisor in Red Hat cloud-init [rhel-8.3.0.z]
Patch26: ci-Add-config-modules-for-controlling-IBM-PowerVM-RMC.-.patch
# For bz#1894015 - Add support for ipv6_autoconf[rhel-8.3.0.z]
Patch27: ci-Explicit-set-IPV6_AUTOCONF-and-IPV6_FORCE_ACCEPT_RA-.patch
# For bz#1894015 - Add support for ipv6_autoconf[rhel-8.3.0.z]
Patch28: ci-net-fix-rendering-of-static6-in-network-config-77.patch
# For bz#1916839 - [Azure] Update existing user password RHEL8x [rhel-8.3.0.z]
Patch29: ci-DataSourceAzure-update-password-for-defuser-if-exist.patch
# For bz#1931835 - SUSE specific option, STARTMODE, should not exist in ifcfg-XXX file. [rhel-8.3.0.z]
Patch30: ci-sysconfig-distro-specific-config-rendering-for-BOOTP.patch
BuildArch: noarch
BuildRequires: pkgconfig(systemd)
BuildRequires: python3-devel
BuildRequires: python3-setuptools
BuildRequires: systemd
# For tests
BuildRequires: iproute
BuildRequires: python3-configobj
# # https://bugzilla.redhat.com/show_bug.cgi?id=1417029
BuildRequires: python3-httpretty >= 0.8.14-2
BuildRequires: python3-jinja2
BuildRequires: python3-jsonpatch
BuildRequires: python3-jsonschema
BuildRequires: python3-mock
BuildRequires: python3-nose
BuildRequires: python3-oauthlib
BuildRequires: python3-prettytable
BuildRequires: python3-pyserial
BuildRequires: python3-PyYAML
BuildRequires: python3-requests
BuildRequires: python3-six
BuildRequires: python3-unittest2
# dnf is needed to make cc_ntp unit tests work
# https://bugs.launchpad.net/cloud-init/+bug/1721573
BuildRequires: /usr/bin/dnf
Requires: e2fsprogs
Requires: iproute
Requires: libselinux-python3
Requires: net-tools
Requires: policycoreutils-python3
Requires: procps
Requires: python3-configobj
Requires: python3-jinja2
Requires: python3-jsonpatch
Requires: python3-jsonschema
Requires: python3-oauthlib
Requires: python3-prettytable
Requires: python3-pyserial
Requires: python3-PyYAML
Requires: python3-requests
Requires: python3-six
Requires: shadow-utils
Requires: util-linux
Requires: xfsprogs
%{?systemd_requires}
%description
Cloud-init is a set of init scripts for cloud instances. Cloud instances
need special scripts to run during initialization to retrieve and install
ssh keys and to let the user run various scripts.
%prep
%autosetup -p1
# Change shebangs
sed -i -e 's|#!/usr/bin/env python|#!/usr/bin/env python3|' \
-e 's|#!/usr/bin/python|#!/usr/bin/python3|' tools/* cloudinit/ssh_util.py
%build
%py3_build
%install
%py3_install --
python3 tools/render-cloudcfg --variant fedora > $RPM_BUILD_ROOT/%{_sysconfdir}/cloud/cloud.cfg
mkdir -p $RPM_BUILD_ROOT/var/lib/cloud
# /run/cloud-init needs a tmpfiles.d entry
mkdir -p $RPM_BUILD_ROOT/run/cloud-init
mkdir -p $RPM_BUILD_ROOT/%{_tmpfilesdir}
cp -p %{SOURCE1} $RPM_BUILD_ROOT/%{_tmpfilesdir}/%{name}.conf
# We supply our own config file since our software differs from Ubuntu's.
cp -p rhel/cloud.cfg $RPM_BUILD_ROOT/%{_sysconfdir}/cloud/cloud.cfg
mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/rsyslog.d
cp -p tools/21-cloudinit.conf $RPM_BUILD_ROOT/%{_sysconfdir}/rsyslog.d/21-cloudinit.conf
# Make installed NetworkManager hook name less generic
mv $RPM_BUILD_ROOT/etc/NetworkManager/dispatcher.d/hook-network-manager \
$RPM_BUILD_ROOT/etc/NetworkManager/dispatcher.d/cloud-init-azure-hook
# Install our own systemd units (rhbz#1440831)
mkdir -p $RPM_BUILD_ROOT%{_unitdir}
cp rhel/systemd/* $RPM_BUILD_ROOT%{_unitdir}/
[ ! -d $RPM_BUILD_ROOT/usr/lib/systemd/system-generators ] && mkdir -p $RPM_BUILD_ROOT/usr/lib/systemd/system-generators
python3 tools/render-cloudcfg --variant rhel systemd/cloud-init-generator.tmpl > $RPM_BUILD_ROOT/usr/lib/systemd/system-generators/cloud-init-generator
chmod 755 $RPM_BUILD_ROOT/usr/lib/systemd/system-generators/cloud-init-generator
[ ! -d $RPM_BUILD_ROOT/usr/lib/%{name} ] && mkdir -p $RPM_BUILD_ROOT/usr/lib/%{name}
cp -p tools/ds-identify $RPM_BUILD_ROOT%{_libexecdir}/%{name}/ds-identify
%clean
rm -rf $RPM_BUILD_ROOT
%post
if [ $1 -eq 1 ] ; then
# Initial installation
# Enabled by default per "runs once then goes away" exception
/bin/systemctl enable cloud-config.service >/dev/null 2>&1 || :
/bin/systemctl enable cloud-final.service >/dev/null 2>&1 || :
/bin/systemctl enable cloud-init.service >/dev/null 2>&1 || :
/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,
# 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 || :
/bin/systemctl is-enabled cloud-final.service >/dev/null 2>&1 &&
/bin/systemctl reenable cloud-final.service >/dev/null 2>&1 || :
/bin/systemctl is-enabled cloud-init.service >/dev/null 2>&1 &&
/bin/systemctl reenable cloud-init.service >/dev/null 2>&1 || :
/bin/systemctl is-enabled cloud-init-local.service >/dev/null 2>&1 &&
/bin/systemctl reenable cloud-init-local.service >/dev/null 2>&1 || :
/bin/systemctl is-enabled cloud-init.target >/dev/null 2>&1 &&
/bin/systemctl reenable cloud-init.target >/dev/null 2>&1 || :
fi
%preun
if [ $1 -eq 0 ] ; then
# Package removal, not upgrade
/bin/systemctl --no-reload disable cloud-config.service >/dev/null 2>&1 || :
/bin/systemctl --no-reload disable cloud-final.service >/dev/null 2>&1 || :
/bin/systemctl --no-reload disable cloud-init.service >/dev/null 2>&1 || :
/bin/systemctl --no-reload disable cloud-init-local.service >/dev/null 2>&1 || :
/bin/systemctl --no-reload disable cloud-init.target >/dev/null 2>&1 || :
# One-shot services -> no need to stop
fi
%postun
%systemd_postun
%files
%license LICENSE
%doc ChangeLog rhel/README.rhel
%config(noreplace) %{_sysconfdir}/cloud/cloud.cfg
%dir %{_sysconfdir}/cloud/cloud.cfg.d
%config(noreplace) %{_sysconfdir}/cloud/cloud.cfg.d/*.cfg
%doc %{_sysconfdir}/cloud/cloud.cfg.d/README
%dir %{_sysconfdir}/cloud/templates
%config(noreplace) %{_sysconfdir}/cloud/templates/*
%{_unitdir}/cloud-config.service
%{_unitdir}/cloud-config.target
%{_unitdir}/cloud-final.service
%{_unitdir}/cloud-init-local.service
%{_unitdir}/cloud-init.service
%{_unitdir}/cloud-init.target
%{_tmpfilesdir}/%{name}.conf
%{python3_sitelib}/*
%{_libexecdir}/%{name}
%{_bindir}/cloud-init*
%doc %{_datadir}/doc/%{name}
%dir %verify(not mode) /run/cloud-init
%dir /var/lib/cloud
/etc/NetworkManager/dispatcher.d/cloud-init-azure-hook
%{_udevrulesdir}/66-azure-ephemeral.rules
%{_sysconfdir}/bash_completion.d/cloud-init
%{_bindir}/cloud-id
%{_libexecdir}/%{name}/ds-identify
/usr/lib/systemd/system-generators/cloud-init-generator
%dir %{_sysconfdir}/rsyslog.d
%config(noreplace) %{_sysconfdir}/rsyslog.d/21-cloudinit.conf
%changelog
* Wed Mar 10 2021 Miroslav Rezanina <mrezanin@redhat.com> - 19.4-11.el8_3.3
- ci-sysconfig-distro-specific-config-rendering-for-BOOTP.patch [bz#1931835]
- Resolves: bz#1931835
(SUSE specific option, STARTMODE, should not exist in ifcfg-XXX file. [rhel-8.3.0.z])
* Tue Jan 26 2021 Miroslav Rezanina <mrezanin@redhat.com> - 19.4-11.el8_3.2
- ci-DataSourceAzure-update-password-for-defuser-if-exist.patch [bz#1916839]
- Resolves: bz#1916839
([Azure] Update existing user password RHEL8x [rhel-8.3.0.z])
* Mon Nov 09 2020 Miroslav Rezanina <mrezanin@redhat.com> - 19.4-11.el8_3.1
- ci-DHCP-sandboxing-failing-on-noexec-mounted-var-tmp-52.patch [bz#1879989]
- ci-network-Fix-type-and-respect-name-when-rendering-vla.patch [bz#1890551]
- ci-Add-config-modules-for-controlling-IBM-PowerVM-RMC.-.patch [bz#1894014]
- ci-Explicit-set-IPV6_AUTOCONF-and-IPV6_FORCE_ACCEPT_RA-.patch [bz#1894015]
- ci-net-fix-rendering-of-static6-in-network-config-77.patch [bz#1894015]
- Resolves: bz#1879989
([Azure][RHEL 8] cloud-init Permission denied with the use of mount option noexec [rhel-8.3.0.z])
- Resolves: bz#1890551
([rhel8][cloud-init] ifup bond0.504 Error: Connection activation failed: No suitable device found for this connection [rhel-8.3.0.z])
- Resolves: bz#1894014
(Support for cloud-init config modules for PowerVM Hypervisor in Red Hat cloud-init [rhel-8.3.0.z])
- Resolves: bz#1894015
(Add support for ipv6_autoconf[rhel-8.3.0.z])
* Wed Sep 02 2020 Miroslav Rezanina <mrezanin@redhat.com> - 19.4-11.el8
- ci-cc_mounts-fix-incorrect-format-specifiers-316.patch [bz#1794664]
- Resolves: bz#1794664
([RHEL8] swapon fails with "swapfile has holes" when created on a xfs filesystem by cloud-init)
* Mon Aug 31 2020 Miroslav Rezanina <mrezanin@redhat.com> - 19.4-10.el8
- ci-Changing-notation-of-subp-call.patch [bz#1839662]
- Resolves: bz#1839662
([ESXi][RHEL8.3][cloud-init]ERROR log in cloud-init.log after clone VM on ESXi platform)
* Mon Aug 24 2020 Miroslav Rezanina <mrezanin@redhat.com> - 19.4-9.el8
- ci-Do-not-use-fallocate-in-swap-file-creation-on-xfs.-7.patch [bz#1794664]
- ci-swap-file-size-being-used-before-checked-if-str-315.patch [bz#1794664]
- ci-Detect-kernel-version-before-swap-file-creation-428.patch [bz#1794664]
- Resolves: bz#1794664
([RHEL8] swapon fails with "swapfile has holes" when created on a xfs filesystem by cloud-init)
* Mon Aug 17 2020 Miroslav Rezanina <mrezanin@redhat.com> - 19.4-8.el8
- ci-When-tools.conf-does-not-exist-running-cmd-vmware-to.patch [bz#1839662]
- ci-ssh-exit-with-non-zero-status-on-disabled-user-472.patch [bz#1833874]
- Resolves: bz#1833874
([rhel-8.3]using root user error should cause a non-zero exit code)
- Resolves: bz#1839662
([ESXi][RHEL8.3][cloud-init]ERROR log in cloud-init.log after clone VM on ESXi platform)
* Fri Jun 26 2020 Miroslav Rezanina <mrezanin@redhat.com> - 19.4-7.el8
- Fixing cloud-init-generator permissions [bz#1834173]
- Resolves: bz#1834173
([rhel-8.3]Incorrect ds-identify check in cloud-init-generator)
* Thu Jun 25 2020 Miroslav Rezanina <mrezanin@redhat.com> - 19.4-6.el8
- ci-ec2-only-redact-token-request-headers-in-logs-avoid-.patch [bz#1822343]
- Resolves: bz#1822343
([RHEL8.3] Do not log IMDSv2 token values into cloud-init.log)
* Wed Jun 24 2020 Miroslav Rezanina <mrezanin@redhat.com> - 19.4-5.el8
- ci-ec2-Do-not-log-IMDSv2-token-values-instead-use-REDAC.patch [bz#1822343]
- ci-Render-the-generator-from-template-instead-of-cp.patch [bz#1834173]
- ci-Change-from-redhat-to-rhel-in-systemd-generator-tmpl.patch [bz#1834173]
- ci-cloud-init.service.tmpl-use-rhel-instead-of-redhat-4.patch [bz#1834173]
- Resolves: bz#1822343
([RHEL8.3] Do not log IMDSv2 token values into cloud-init.log)
- Resolves: bz#1834173
([rhel-8.3]Incorrect ds-identify check in cloud-init-generator)
* Tue Jun 09 2020 Miroslav Rezanina <mrezanin@redhat.com> - 19.4-4.el8
- ci-changing-ds-identify-patch-from-usr-lib-to-usr-libex.patch [bz#1834173]
- Resolves: bz#1834173
([rhel-8.3]Incorrect ds-identify check in cloud-init-generator)
* Mon Jun 01 2020 Miroslav Rezanina <mrezanin@redhat.com> - 19.4-3.el8
- ci-Make-cloud-init.service-execute-after-network-is-up.patch [bz#1803928]
- Resolves: bz#1803928
([RHEL8.3] Race condition of starting cloud-init and NetworkManager)
* Thu May 28 2020 Miroslav Rezanina <mrezanin@redhat.com> - 19.4-2.el8
- ci-cc_set_password-increase-random-pwlength-from-9-to-2.patch [bz#1812171]
- ci-utils-use-SystemRandom-when-generating-random-passwo.patch [bz#1812174]
- ci-Enable-ssh_deletekeys-by-default.patch [bz#1814152]
- ci-Remove-race-condition-between-cloud-init-and-Network.patch [bz#1840648]
- Resolves: bz#1812171
(CVE-2020-8632 cloud-init: Too short random password length in cc_set_password in config/cc_set_passwords.py [rhel-8])
- Resolves: bz#1812174
(CVE-2020-8631 cloud-init: Use of random.choice when generating random password [rhel-8])
- Resolves: bz#1814152
(CVE-2018-10896 cloud-init: default configuration disabled deletion of SSH host keys [rhel-8])
- Resolves: bz#1840648
([cloud-init][RHEL-8.2.0] /etc/resolv.conf lose config after reboot (initial instance is ok))
* Mon Apr 20 2020 Miroslav Rezanina <mrezanin@redhat.coM> - 19.4-1.el8
- Rebase to cloud-init 19.4 [bz#1803095]
- Resolves: bz#1803095
([RHEL-8.3.0] cloud-init rebase to 19.4)
* Tue Mar 10 2020 Miroslav Rezanina <mrezanin@redhat.com> - 18.5-12.el8
- ci-Remove-race-condition-between-cloud-init-and-Network.patch [bz#1807797]
- Resolves: bz#1807797
([cloud-init][RHEL-8.2.0] /etc/resolv.conf lose config after reboot (initial instance is ok))
* Thu Feb 20 2020 Miroslav Rezanina <mrezanin@redhat.com> - 18.5-11.el8
- ci-azure-avoid-re-running-cloud-init-when-instance-id-i.patch [bz#1788684]
- ci-net-skip-bond-interfaces-in-get_interfaces.patch [bz#1768770]
- ci-net-add-is_master-check-for-filtering-device-list.patch [bz#1768770]
- Resolves: bz#1768770
(cloud-init complaining about enslaved mac)
- Resolves: bz#1788684
([RHEL-8] cloud-init Azure byte swap (hyperV Gen2 Only))
* Thu Feb 13 2020 Miroslav Rezanina <mrezanin@redhat.com> - 18.5-10.el8
- ci-cmd-main.py-Fix-missing-modules-init-key-in-modes-di.patch [bz#1802140]
- Resolves: bz#1802140
([cloud-init][RHEL8.2]cloud-init cloud-final.service fail with KeyError: 'modules-init' after upgrade to version 18.2-1.el7_6.1 in RHV)
* Tue Jan 28 2020 Miroslav Rezanina <mrezanin@redhat.com> - 18.5-9.el8
- ci-Removing-cloud-user-from-wheel.patch [bz#1785648]
- Resolves: bz#1785648
([RHEL8]cloud-user added to wheel group and sudoers.d causes 'sudo -v' prompts for passphrase)
* Fri Nov 22 2019 Miroslav Rezanina <mrezanin@redhat.com> - 18.5-8.el8
- ci-Fix-for-network-configuration-not-persisting-after-r.patch [bz#1706482]
- ci-util-json.dumps-on-python-2.7-will-handle-UnicodeDec.patch [bz#1744718]
- Resolves: bz#1706482
([cloud-init][RHVM]cloud-init network configuration does not persist reboot [RHEL 8.2.0])
- Resolves: bz#1744718
([cloud-init][RHEL8][OpenStack] cloud-init can't persist instance-data.json)
* Mon Jul 15 2019 Miroslav Rezanina <mrezanin@redhat.com> - 18.5-7.el8
- Fixing TPS [bz#1729864]
- Resolves: bz#1729864
(cloud-init tps fail)
* Thu Jul 04 2019 Miroslav Rezanina <mrezanin@redhat.com> - 18.5-6.el8
- ci-Revert-azure-ensure-that-networkmanager-hook-script-.patch [bz#1692914]
- ci-Azure-Return-static-fallback-address-as-if-failed-to.patch [bz#1691986]
- Resolves: bz#1691986
([Azure] [RHEL 8.1] Cloud-init fixes to support fast provisioning for Azure)
- Resolves: bz#1692914
([8.1] [WALA][cloud] cloud-init dhclient-hook script has some unexpected side-effects on Azure)
* Mon Jun 03 2019 Miroslav Rezanina <mrezanin@redhat.com> - 18.5-4.el8
- ci-Azure-Ensure-platform-random_seed-is-always-serializ.patch [bz#1691986]
- ci-DatasourceAzure-add-additional-logging-for-azure-dat.patch [bz#1691986]
- ci-Azure-Changes-to-the-Hyper-V-KVP-Reporter.patch [bz#1691986]
- ci-DataSourceAzure-Adjust-timeout-for-polling-IMDS.patch [bz#1691986]
- ci-cc_mounts-check-if-mount-a-on-no-change-fstab-path.patch [bz#1691986]
- Resolves: bz#1691986
([Azure] [RHEL 8.1] Cloud-init fixes to support fast provisioning for Azure)
* Tue Apr 16 2019 Danilo Cesar Lemes de Paula <ddepaula@redhat.com> - 18.5-3.el8
- ci-Adding-gating-tests-for-Azure-ESXi-and-AWS.patch [bz#1682786]
- Resolves: bz#1682786
(cloud-init changes blocked until gating tests are added)
* Wed Apr 10 2019 Danilo C. L. de Paula <ddepaula@redhat.com> - 18.5-2
- Adding gating.yaml file
- Resolves: rhbz#1682786
(cloud-init changes blocked until gating tests are added)
* Wed Apr 10 2019 Danilo de Paula <ddepaula@redhat.com: - 18.5-1.el8
- Rebase to cloud-init 18.5
- Resolves: bz#1687563
(cloud-init 18.5 rebase for fast provisioning on Azure [RHEL 8.0.1])
* Wed Jan 23 2019 Miroslav Rezanina <mrezanin@redhat.com> - 18.2-6.el8
- ci-net-Make-sysconfig-renderer-compatible-with-Network-.patch [bz#1602784]
- Resolves: bz#1602784
(cloud-init: Sometimes image boots fingerprints is configured, there's a network device present but it's not configured)
* Fri Jan 18 2019 Miroslav Rezanina <mrezanin@redhat.com> - 18.2-5.el8
- ci-Fix-string-missmatch-when-mounting-ntfs.patch [bz#1664227]
- Resolves: bz#1664227
([Azure]String missmatch causes the /dev/sdb1 mounting failed after stop&start VM)
* Thu Jan 10 2019 Miroslav Rezanina <mrezanin@redhat.com> - 18.2-4.el8
- ci-Enable-cloud-init-by-default-on-vmware.patch [bz#1644335]
- Resolves: bz#1644335
([ESXi][RHEL8.0]Enable cloud-init by default on VMware)
* Wed Nov 28 2018 Miroslav Rezanina <mrezanin@redhat.com> - 18.2-3.el8
- ci-Adding-systemd-mount-options-to-wait-for-cloud-init.patch [bz#1615599]
- ci-Azure-Ignore-NTFS-mount-errors-when-checking-ephemer.patch [bz#1615599]
- ci-azure-Add-reported-ready-marker-file.patch [bz#1615599]
- ci-Adding-disk_setup-to-rhel-cloud.cfg.patch [bz#1615599]
- Resolves: bz#1615599
([Azure] cloud-init fails to mount /dev/sdb1 after stop(deallocate)&&start VM)
* Tue Nov 06 2018 Miroslav Rezanina <mrezanin@redhat.com> - 18.2-2.el7
- Revert "remove 'tee' command from logging configuration" [bz#1626117]
- Resolves: rhbz#1626117]
(cloud-init-0.7.9-9 doesn't feed cloud-init-output.log)
* Fri Jun 29 2018 Miroslav Rezanina <mrezanin@redhat.com> - 18.2-1.el7
- Rebase to 18.2 [bz#1515909]
Resolves: rhbz#1515909
* Tue Feb 13 2018 Ryan McCabe <rmccabe@redhat.com> 0.7.9-24
- Set DHCP_HOSTNAME on Azure to allow for the hostname to be
published correctly when bouncing the network.
Resolves: rhbz#1434109
* Mon Jan 15 2018 Ryan McCabe <rmccabe@redhat.com> 0.7.9-23
- Fix a bug tha caused cloud-init to fail as a result of trying
to rename bonds.
Resolves: rhbz#1512247
* Mon Jan 15 2018 Ryan McCabe <rmccabe@redhat.com> 0.7.9-22
- Apply patch from -21
Resolves: rhbz#1489270
* Mon Jan 15 2018 Ryan McCabe <rmccabe@redhat.com> 0.7.9-21
- sysconfig: Fix a potential traceback introduced in the
0.7.9-17 build
Resolves: rhbz#1489270
* Sun Dec 17 2017 Ryan McCabe <rmccabe@redhat.com> 0.7.9-20
- sysconfig: Correct rendering for dhcp on ipv6
Resolves: rhbz#1519271
* Thu Nov 30 2017 Ryan McCabe <rmccabe@redhat.com> 0.7.9-19
- sysconfig: Fix rendering of default gateway for ipv6
Resolves: rhbz#1492726
* Fri Nov 24 2017 Ryan McCabe <rmccabe@redhat.com> 0.7.9-18
- Start the cloud-init init local service after the dbus socket is created
so that the hostnamectl command works.
Resolves: rhbz#1450521
* Tue Nov 21 2017 Ryan McCabe <rmccabe@redhat.com> 0.7.9-17
- Correctly render DNS and DOMAIN for sysconfig
Resolves: rhbz#1489270
* Mon Nov 20 2017 Ryan McCabe <rmccabe@redhat.com> 0.7.9-16
- Disable NetworkManager management of resolv.conf if nameservers
are specified by configuration.
Resolves: rhbz#1454491
* Mon Nov 13 2017 Ryan McCabe <rmccabe@redhat.com> 0.7.9-15
- Fix a null reference error in the rh_subscription module
Resolves: rhbz#1498974
* Mon Nov 13 2017 Ryan McCabe <rmccabe@redhat.com> 0-7.9-14
- Include gateway if it's included in subnet configration
Resolves: rhbz#1492726
* Sun Nov 12 2017 Ryan McCabe <rmccabe@redhat.com> 0-7.9-13
- Do proper cleanup of systemd units when upgrading from versions
0.7.9-3 through 0.7.9-8.
Resolves: rhbz#1465730
* Thu Nov 09 2017 Ryan McCabe <rmccabe@redhat.com> 0.7.9-12
- Prevent Azure NM and dhclient hooks from running when cloud-init is
disabled (rhbz#1474226)
* Tue Oct 31 2017 Ryan McCabe <rmccabe@redhat.com> 0.7.9-11
- Fix rendering of multiple static IPs per interface file
Resolves: rhbz#bz1497954
* Tue Sep 26 2017 Ryan McCabe <rmccabe@redhat.com> 0.7.9-10
- AliCloud: Add support for the Alibaba Cloud datasource (rhbz#1482547)
* Thu Jun 22 2017 Lars Kellogg-Stedman <lars@redhat.com> 0.7.9-9
- RHEL/CentOS: Fix default routes for IPv4/IPv6 configuration. (rhbz#1438082)
- azure: ensure that networkmanager hook script runs (rhbz#1440831 rhbz#1460206)
- Fix ipv6 subnet detection (rhbz#1438082)
* Tue May 23 2017 Lars Kellogg-Stedman <lars@redhat.com> 0.7.9-8
- Update patches
* Mon May 22 2017 Lars Kellogg-Stedman <lars@redhat.com> 0.7.9-7
- Add missing sysconfig unit test data (rhbz#1438082)
- Fix dual stack IPv4/IPv6 configuration for RHEL (rhbz#1438082)
- sysconfig: Raise ValueError when multiple default gateways are present. (rhbz#1438082)
- Bounce network interface for Azure when using the built-in path. (rhbz#1434109)
- Do not write NM_CONTROLLED=no in generated interface config files (rhbz#1385172)
* Wed May 10 2017 Lars Kellogg-Stedman <lars@redhat.com> 0.7.9-6
- add power-state-change module to cloud_final_modules (rhbz#1252477)
- remove 'tee' command from logging configuration (rhbz#1424612)
- limit permissions on def_log_file (rhbz#1424612)
- Bounce network interface for Azure when using the built-in path. (rhbz#1434109)
- OpenStack: add 'dvs' to the list of physical link types. (rhbz#1442783)
* Wed May 10 2017 Lars Kellogg-Stedman <lars@redhat.com> 0.7.9-5
- systemd: replace generator with unit conditionals (rhbz#1440831)
* Thu Apr 13 2017 Charalampos Stratakis <cstratak@redhat.com> 0.7.9-4
- Import to RHEL 7
Resolves: rhbz#1427280
* Tue Mar 07 2017 Lars Kellogg-Stedman <lars@redhat.com> 0.7.9-3
- fixes for network config generation
- avoid dependency cycle at boot (rhbz#1420946)
* Tue Jan 17 2017 Lars Kellogg-Stedman <lars@redhat.com> 0.7.9-2
- use timeout from datasource config in openstack get_data (rhbz#1408589)
* Thu Dec 01 2016 Lars Kellogg-Stedman <lars@redhat.com> - 0.7.9-1
- Rebased on upstream 0.7.9.
- Remove dependency on run-parts
* Wed Jan 06 2016 Lars Kellogg-Stedman <lars@redhat.com> - 0.7.6-8
- make rh_subscription plugin do nothing in the absence of a valid
configuration [RH:1295953]
- move rh_subscription module to cloud_config stage
* Wed Jan 06 2016 Lars Kellogg-Stedman <lars@redhat.com> - 0.7.6-7
- correct permissions on /etc/ssh/sshd_config [RH:1296191]
* Thu Sep 03 2015 Lars Kellogg-Stedman <lars@redhat.com> - 0.7.6-6
- rebuild for ppc64le
* Tue Jul 07 2015 Lars Kellogg-Stedman <lars@redhat.com> - 0.7.6-5
- bump revision for new build
* Tue Jul 07 2015 Lars Kellogg-Stedman <lars@redhat.com> - 0.7.6-4
- ensure rh_subscription plugin is enabled by default
* Wed Apr 29 2015 Lars Kellogg-Stedman <lars@redhat.com> - 0.7.6-3
- added dependency on python-jinja2 [RH:1215913]
- added rhn_subscription plugin [RH:1227393]
- require pyserial to support smartos data source [RH:1226187]
* Fri Jan 16 2015 Lars Kellogg-Stedman <lars@redhat.com> - 0.7.6-2
- Rebased RHEL version to Fedora rawhide
- Backported fix for https://bugs.launchpad.net/cloud-init/+bug/1246485
- Backported fix for https://bugs.launchpad.net/cloud-init/+bug/1411829
* Fri Nov 14 2014 Colin Walters <walters@redhat.com> - 0.7.6-1
- New upstream version [RH:974327]
- Drop python-cheetah dependency (same as above bug)