forked from pool/cloud-init
Accepting request 591769 from Cloud:Tools
- Update to version 18.1 (bsc#1085787, bsc#1084749) + Forward port cloud-init-python2-sigpipe.patch + Forward port 0003-Distro-dependent-chrony-config-file.patch partial integration into 0001-Support-chrony-configuration-lp-1731619.patch + Forward port cloud-init-no-python-linux-dist.patch + Remove 0002-Disable-method-deprecation-warning-for-pylint.patch use new cloud-init internal distro detection code + Remove cloud-init-resize-ro-btrfs.patch included upstream + Remove 0001-Set-syslog_fix_perms-for-SUSE-distro-addresses-bsc-1.patch included upstream + OVF: Fix VMware support for 64-bit platforms. [Sankar Tanguturi] + ds-identify: Fix searching for iso9660 OVF cdroms. (LP: #1749980) + SUSE: Fix groups used for ownership of cloud-init.log [Robert Schweikert] + ds-identify: check /writable/system-data/ for nocloud seed. (LP: #1747070) + tests: run nosetests in cloudinit/ directory, fix py26 fallout. + tools: run-centos: git clone rather than tar. + tests: add support for logs with lxd from snap and future lxd 3. (LP: #1745663) + EC2: Fix get_instance_id called against cached datasource pickle. (LP: #1748354) + cli: fix cloud-init status to report running when before result.json (LP: #1747965) + net: accept network-config in netplan format for renaming interfaces (LP: #1709715) + Fix ssh keys validation in ssh_util [Tatiana Kholkina] + docs: Update RTD content for cloud-init subcommands. + OVF: Extend well-known labels to include OVFENV. (LP: #1698669) + Fix potential cases of uninitialized variables. (LP: #1744796) + tests: Collect script output as binary, collect systemd journal, fix lxd. OBS-URL: https://build.opensuse.org/request/show/591769 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/cloud-init?expand=0&rev=49
This commit is contained in:
commit
64e80bc062
@ -1,28 +0,0 @@
|
|||||||
From 28167e24ae4a0e744103a71061474836dc6a9559 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Robert Schweikert <rjschwei@suse.com>
|
|
||||||
Date: Tue, 13 Feb 2018 14:28:51 -0500
|
|
||||||
Subject: [PATCH] - Set syslog_fix_perms for SUSE distro, addresses bsc#1080595
|
|
||||||
+ Avoid using the default configuration for syslog ownership the neither
|
|
||||||
"adm" nor "wheel" groups are part of the default config on SUSE distros
|
|
||||||
|
|
||||||
---
|
|
||||||
config/cloud.cfg.tmpl | 3 +++
|
|
||||||
1 file changed, 3 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl
|
|
||||||
index 32de9c9b..3ab681ee 100644
|
|
||||||
--- a/config/cloud.cfg.tmpl
|
|
||||||
+++ b/config/cloud.cfg.tmpl
|
|
||||||
@@ -5,6 +5,9 @@
|
|
||||||
{% if variant in ["freebsd"] %}
|
|
||||||
syslog_fix_perms: root:wheel
|
|
||||||
{% endif %}
|
|
||||||
+{% if variant in ["suse"] %}
|
|
||||||
+syslog_fix_perms: root:adm
|
|
||||||
+{% endif %}
|
|
||||||
# A set of users which may be applied and/or used by various modules
|
|
||||||
# when a 'default' entry is found it will reference the 'default_user'
|
|
||||||
# from the distro configuration specified below
|
|
||||||
--
|
|
||||||
2.13.6
|
|
||||||
|
|
@ -28,10 +28,8 @@ Subject: [PATCH 1/3] - Support chrony configuration (lp#1731619) + Add a
|
|||||||
13 files changed, 400 insertions(+), 40 deletions(-)
|
13 files changed, 400 insertions(+), 40 deletions(-)
|
||||||
create mode 100644 templates/chrony.conf.tmpl
|
create mode 100644 templates/chrony.conf.tmpl
|
||||||
|
|
||||||
diff --git a/cloudinit/config/cc_ntp.py b/cloudinit/config/cc_ntp.py
|
--- cloudinit/config/cc_ntp.py.orig
|
||||||
index f50bcb35..2f662a9e 100644
|
+++ cloudinit/config/cc_ntp.py
|
||||||
--- a/cloudinit/config/cc_ntp.py
|
|
||||||
+++ b/cloudinit/config/cc_ntp.py
|
|
||||||
@@ -20,8 +20,9 @@ from textwrap import dedent
|
@@ -20,8 +20,9 @@ from textwrap import dedent
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -44,30 +42,41 @@ index f50bcb35..2f662a9e 100644
|
|||||||
NR_POOL_SERVERS = 4
|
NR_POOL_SERVERS = 4
|
||||||
distros = ['centos', 'debian', 'fedora', 'opensuse', 'sles', 'ubuntu']
|
distros = ['centos', 'debian', 'fedora', 'opensuse', 'sles', 'ubuntu']
|
||||||
|
|
||||||
@@ -110,26 +111,48 @@ def handle(name, cfg, cloud, log, _args):
|
@@ -49,6 +50,7 @@ schema = {
|
||||||
" but not a dictionary type,"
|
'examples': [
|
||||||
" is a %s %instead"), type_utils.obj_name(ntp_cfg))
|
dedent("""\
|
||||||
|
ntp:
|
||||||
|
+ enabled: true
|
||||||
|
pools: [0.int.pool.ntp.org, 1.int.pool.ntp.org, ntp.myorg.org]
|
||||||
|
servers:
|
||||||
|
- ntp.server.local
|
||||||
|
@@ -60,6 +62,9 @@ schema = {
|
||||||
|
'ntp': {
|
||||||
|
'type': ['object', 'null'],
|
||||||
|
'properties': {
|
||||||
|
+ 'enabled': {
|
||||||
|
+ "type": "boolean"
|
||||||
|
+ },
|
||||||
|
'pools': {
|
||||||
|
'type': 'array',
|
||||||
|
'items': {
|
||||||
|
@@ -110,26 +115,48 @@ def handle(name, cfg, cloud, log, _args)
|
||||||
|
"'ntp' key existed in config, but not a dictionary type,"
|
||||||
|
" is a {_type} instead".format(_type=type_utils.obj_name(ntp_cfg)))
|
||||||
|
|
||||||
- validate_cloudconfig_schema(cfg, schema)
|
+ if ntp_cfg.get('enabled') and ntp_cfg.get('enabled') == 'true':
|
||||||
|
+ cloud.distro.set_timesync_client()
|
||||||
|
+ else:
|
||||||
|
+ # When all distro implementations are switched return here
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
validate_cloudconfig_schema(cfg, schema)
|
||||||
- if ntp_installable():
|
- if ntp_installable():
|
||||||
- service_name = 'ntp'
|
- service_name = 'ntp'
|
||||||
- confpath = NTP_CONF
|
- confpath = NTP_CONF
|
||||||
- template_name = None
|
- template_name = None
|
||||||
- packages = ['ntp']
|
- packages = ['ntp']
|
||||||
- check_exe = 'ntpd'
|
- check_exe = 'ntpd'
|
||||||
+ if ntp_cfg.get('enabled') and ntp_cfg.get('enabled') == 'true':
|
|
||||||
+ cloud.distro.set_timesync_client()
|
|
||||||
else:
|
|
||||||
- service_name = 'systemd-timesyncd'
|
|
||||||
- confpath = TIMESYNCD_CONF
|
|
||||||
- template_name = 'timesyncd.conf'
|
|
||||||
- packages = []
|
|
||||||
- check_exe = '/lib/systemd/systemd-timesyncd'
|
|
||||||
+ # When all distro implementations are switched return here
|
|
||||||
+ pass
|
|
||||||
|
|
||||||
- rename_ntp_conf()
|
|
||||||
+ validate_cloudconfig_schema(cfg, schema)
|
|
||||||
+ if hasattr(cloud.distro, 'timesync_client'):
|
+ if hasattr(cloud.distro, 'timesync_client'):
|
||||||
+ client_name = cloud.distro.timesync_client
|
+ client_name = cloud.distro.timesync_client
|
||||||
+ service_name = cloud.distro.timesync_service_name
|
+ service_name = cloud.distro.timesync_service_name
|
||||||
@ -79,8 +88,13 @@ index f50bcb35..2f662a9e 100644
|
|||||||
+ template_name = 'timesyncd.conf'
|
+ template_name = 'timesyncd.conf'
|
||||||
+ elif client_name == 'chrony':
|
+ elif client_name == 'chrony':
|
||||||
+ confpath = CHRONY_CONF_FILE
|
+ confpath = CHRONY_CONF_FILE
|
||||||
+ template_name = 'chrony.conf'
|
+ template_name = 'chrony.conf.%s' % cloud.distro.name
|
||||||
+ else:
|
else:
|
||||||
|
- service_name = 'systemd-timesyncd'
|
||||||
|
- confpath = TIMESYNCD_CONF
|
||||||
|
- template_name = 'timesyncd.conf'
|
||||||
|
- packages = []
|
||||||
|
- check_exe = '/lib/systemd/systemd-timesyncd'
|
||||||
+ if ntp_installable():
|
+ if ntp_installable():
|
||||||
+ service_name = 'ntp'
|
+ service_name = 'ntp'
|
||||||
+ confpath = NTP_CONF_FILE
|
+ confpath = NTP_CONF_FILE
|
||||||
@ -93,7 +107,8 @@ index f50bcb35..2f662a9e 100644
|
|||||||
+ template_name = 'timesyncd.conf'
|
+ template_name = 'timesyncd.conf'
|
||||||
+ packages = []
|
+ packages = []
|
||||||
+ check_exe = '/lib/systemd/systemd-timesyncd'
|
+ check_exe = '/lib/systemd/systemd-timesyncd'
|
||||||
+
|
|
||||||
|
- rename_ntp_conf()
|
||||||
+ rename_ntp_conf(confpath)
|
+ rename_ntp_conf(confpath)
|
||||||
# ensure when ntp is installed it has a configuration file
|
# ensure when ntp is installed it has a configuration file
|
||||||
# to use instead of starting up with packaged defaults
|
# to use instead of starting up with packaged defaults
|
||||||
@ -108,7 +123,7 @@ index f50bcb35..2f662a9e 100644
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
reload_ntp(service_name, systemd=cloud.distro.uses_systemd())
|
reload_ntp(service_name, systemd=cloud.distro.uses_systemd())
|
||||||
@@ -167,7 +190,7 @@ def install_ntp(install_func, packages=None, check_exe="ntpd"):
|
@@ -167,7 +194,7 @@ def install_ntp(install_func, packages=N
|
||||||
def rename_ntp_conf(config=None):
|
def rename_ntp_conf(config=None):
|
||||||
"""Rename any existing ntp.conf file"""
|
"""Rename any existing ntp.conf file"""
|
||||||
if config is None: # For testing
|
if config is None: # For testing
|
||||||
@ -117,11 +132,9 @@ index f50bcb35..2f662a9e 100644
|
|||||||
if os.path.exists(config):
|
if os.path.exists(config):
|
||||||
util.rename(config, config + ".dist")
|
util.rename(config, config + ".dist")
|
||||||
|
|
||||||
diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py
|
--- cloudinit/distros/__init__.py.orig
|
||||||
index 99e60e7a..41ae097d 100755
|
+++ cloudinit/distros/__init__.py
|
||||||
--- a/cloudinit/distros/__init__.py
|
@@ -61,6 +61,9 @@ class Distro(object):
|
||||||
+++ b/cloudinit/distros/__init__.py
|
|
||||||
@@ -57,6 +57,9 @@ class Distro(object):
|
|
||||||
init_cmd = ['service'] # systemctl, service etc
|
init_cmd = ['service'] # systemctl, service etc
|
||||||
renderer_configs = {}
|
renderer_configs = {}
|
||||||
|
|
||||||
@ -131,7 +144,7 @@ index 99e60e7a..41ae097d 100755
|
|||||||
def __init__(self, name, cfg, paths):
|
def __init__(self, name, cfg, paths):
|
||||||
self._paths = paths
|
self._paths = paths
|
||||||
self._cfg = cfg
|
self._cfg = cfg
|
||||||
@@ -86,6 +89,43 @@ class Distro(object):
|
@@ -90,6 +93,43 @@ class Distro(object):
|
||||||
renderer.render_network_config(network_config=network_config)
|
renderer.render_network_config(network_config=network_config)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@ -175,149 +188,9 @@ index 99e60e7a..41ae097d 100755
|
|||||||
def _find_tz_file(self, tz):
|
def _find_tz_file(self, tz):
|
||||||
tz_file = os.path.join(self.tz_zone_dir, str(tz))
|
tz_file = os.path.join(self.tz_zone_dir, str(tz))
|
||||||
if not os.path.isfile(tz_file):
|
if not os.path.isfile(tz_file):
|
||||||
diff --git a/cloudinit/distros/arch.py b/cloudinit/distros/arch.py
|
|
||||||
index f87a3432..fffc1c9c 100644
|
|
||||||
--- a/cloudinit/distros/arch.py
|
|
||||||
+++ b/cloudinit/distros/arch.py
|
|
||||||
@@ -153,6 +153,10 @@ class Distro(distros.Distro):
|
|
||||||
self._runner.run("update-sources", self.package_command,
|
|
||||||
["-y"], freq=PER_INSTANCE)
|
|
||||||
|
|
||||||
+ def _set_default_timesync_client(self):
|
|
||||||
+ # Fall back to previous implementation
|
|
||||||
+ return
|
|
||||||
+
|
|
||||||
|
|
||||||
def _render_network(entries, target="/", conf_dir="etc/netctl",
|
|
||||||
resolv_conf="etc/resolv.conf", enable_func=None):
|
|
||||||
diff --git a/cloudinit/distros/debian.py b/cloudinit/distros/debian.py
|
|
||||||
index 33cc0bf1..46dd4173 100644
|
|
||||||
--- a/cloudinit/distros/debian.py
|
|
||||||
+++ b/cloudinit/distros/debian.py
|
|
||||||
@@ -212,6 +212,10 @@ class Distro(distros.Distro):
|
|
||||||
(arch, _err) = util.subp(['dpkg', '--print-architecture'])
|
|
||||||
return str(arch).strip()
|
|
||||||
|
|
||||||
+ def _set_default_timesync_client(self):
|
|
||||||
+ # Fall back to previous implementation
|
|
||||||
+ return
|
|
||||||
+
|
|
||||||
|
|
||||||
def _get_wrapper_prefix(cmd, mode):
|
|
||||||
if isinstance(cmd, str):
|
|
||||||
diff --git a/cloudinit/distros/freebsd.py b/cloudinit/distros/freebsd.py
|
|
||||||
index bad112fe..00b38917 100644
|
|
||||||
--- a/cloudinit/distros/freebsd.py
|
|
||||||
+++ b/cloudinit/distros/freebsd.py
|
|
||||||
@@ -649,4 +649,8 @@ class Distro(distros.Distro):
|
|
||||||
self._runner.run("update-sources", self.package_command,
|
|
||||||
["update"], freq=PER_INSTANCE)
|
|
||||||
|
|
||||||
+ def _set_default_timesync_client(self):
|
|
||||||
+ # Fall back to previous implementation
|
|
||||||
+ return
|
|
||||||
+
|
|
||||||
# vi: ts=4 expandtab
|
|
||||||
diff --git a/cloudinit/distros/gentoo.py b/cloudinit/distros/gentoo.py
|
|
||||||
index dc57717d..5685b058 100644
|
|
||||||
--- a/cloudinit/distros/gentoo.py
|
|
||||||
+++ b/cloudinit/distros/gentoo.py
|
|
||||||
@@ -214,6 +214,10 @@ class Distro(distros.Distro):
|
|
||||||
self._runner.run("update-sources", self.package_command,
|
|
||||||
["-u", "world"], freq=PER_INSTANCE)
|
|
||||||
|
|
||||||
+ def _set_default_timesync_client(self):
|
|
||||||
+ # Fall back to previous implementation
|
|
||||||
+ return
|
|
||||||
+
|
|
||||||
|
|
||||||
def convert_resolv_conf(settings):
|
|
||||||
"""Returns a settings string formatted for resolv.conf."""
|
|
||||||
diff --git a/cloudinit/distros/opensuse.py b/cloudinit/distros/opensuse.py
|
|
||||||
index a219e9fb..092d6a11 100644
|
|
||||||
--- a/cloudinit/distros/opensuse.py
|
|
||||||
+++ b/cloudinit/distros/opensuse.py
|
|
||||||
@@ -8,6 +8,8 @@
|
|
||||||
#
|
|
||||||
# This file is part of cloud-init. See LICENSE file for license information.
|
|
||||||
|
|
||||||
+import platform
|
|
||||||
+
|
|
||||||
from cloudinit import distros
|
|
||||||
|
|
||||||
from cloudinit.distros.parsers.hostname import HostnameConf
|
|
||||||
@@ -36,6 +38,23 @@ class Distro(distros.Distro):
|
|
||||||
systemd_locale_conf_fn = '/etc/locale.conf'
|
|
||||||
tz_local_fn = '/etc/localtime'
|
|
||||||
|
|
||||||
+ __timesync_client_map = {
|
|
||||||
+ # Map the system_info supported values
|
|
||||||
+ 'chrony': ('chrony', 'chronyd'),
|
|
||||||
+ 'isc-ntp': ('ntp', 'ntpd'),
|
|
||||||
+ 'systemd-timesyncd': ('systemd-timesyncd', 'systemd-timesyncd'),
|
|
||||||
+ # Map the common names if different from system_info
|
|
||||||
+ 'chronyd': ('chrony', 'chronyd'),
|
|
||||||
+ 'ntpd': ('ntp', 'ntpd'),
|
|
||||||
+ '/usr/lib/systemd/systemd-timesyncd':
|
|
||||||
+ ('systemd-timesyncd', 'systemd-timesyncd')
|
|
||||||
+ }
|
|
||||||
+ __ntp_client_execs = [
|
|
||||||
+ 'chronyd',
|
|
||||||
+ 'ntpd',
|
|
||||||
+ '/usr/lib/systemd/systemd-timesyncd'
|
|
||||||
+ ]
|
|
||||||
+
|
|
||||||
def __init__(self, name, cfg, paths):
|
|
||||||
distros.Distro.__init__(self, name, cfg, paths)
|
|
||||||
self._runner = helpers.Runners(paths)
|
|
||||||
@@ -145,6 +164,28 @@ class Distro(distros.Distro):
|
|
||||||
host_fn = self.hostname_conf_fn
|
|
||||||
return (host_fn, self._read_hostname(host_fn))
|
|
||||||
|
|
||||||
+ def _set_default_timesync_client(self):
|
|
||||||
+ """The default timesync client is dependent on the distribution."""
|
|
||||||
+ # When we get here the user has configured ntp to be enabled but
|
|
||||||
+ # no client is installed
|
|
||||||
+ distro_info = platform.linux_distribution()
|
|
||||||
+ name = distro_info[0]
|
|
||||||
+ major_ver = int(distro_info[1].split('.')[0])
|
|
||||||
+
|
|
||||||
+ # This is horribly complicated because of a case of
|
|
||||||
+ # "we do not care if versions should be increasing syndrome"
|
|
||||||
+ if (
|
|
||||||
+ (major_ver >= 15 and 'openSUSE' not in name) or
|
|
||||||
+ (major_ver >= 15 and 'openSUSE' in name and major_ver != 42)
|
|
||||||
+ ):
|
|
||||||
+ self.timesync_client = 'chrony'
|
|
||||||
+ self.timesync_service_name = 'chronyd'
|
|
||||||
+ self.install_packages(['chrony'])
|
|
||||||
+ else:
|
|
||||||
+ self.timesync_client = 'ntp'
|
|
||||||
+ self.timesync_service_name = 'ntpd'
|
|
||||||
+ self.install_packages(['ntp'])
|
|
||||||
+
|
|
||||||
def _write_hostname(self, hostname, out_fn):
|
|
||||||
if self.uses_systemd() and out_fn.endswith('/previous-hostname'):
|
|
||||||
util.write_file(out_fn, hostname)
|
|
||||||
diff --git a/cloudinit/distros/rhel.py b/cloudinit/distros/rhel.py
|
|
||||||
index 1fecb619..6d9c9f67 100644
|
|
||||||
--- a/cloudinit/distros/rhel.py
|
|
||||||
+++ b/cloudinit/distros/rhel.py
|
|
||||||
@@ -218,4 +218,8 @@ class Distro(distros.Distro):
|
|
||||||
self._runner.run("update-sources", self.package_command,
|
|
||||||
["makecache"], freq=PER_INSTANCE)
|
|
||||||
|
|
||||||
+ def _set_default_timesync_client(self):
|
|
||||||
+ # Fall back to previous implementation
|
|
||||||
+ return
|
|
||||||
+
|
|
||||||
# vi: ts=4 expandtab
|
|
||||||
diff --git a/templates/chrony.conf.tmpl b/templates/chrony.conf.tmpl
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..38e84d85
|
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/templates/chrony.conf.tmpl
|
+++ templates/chrony.conf.tmpl
|
||||||
@@ -0,0 +1,25 @@
|
@@ -0,0 +1,24 @@
|
||||||
+## template:jinja
|
+## template:jinja
|
||||||
+# cloud-init generated file
|
+# cloud-init generated file
|
||||||
+# See chrony.conf(5)
|
+# See chrony.conf(5)
|
||||||
@ -342,441 +215,58 @@ index 00000000..38e84d85
|
|||||||
+
|
+
|
||||||
+# Enable kernel synchronization of the real-time clock (RTC).
|
+# Enable kernel synchronization of the real-time clock (RTC).
|
||||||
+rtcsync
|
+rtcsync
|
||||||
+
|
--- cloudinit/distros/opensuse.py.orig
|
||||||
diff --git a/tests/unittests/test_distros/test_generic.py b/tests/unittests/test_distros/test_generic.py
|
+++ cloudinit/distros/opensuse.py
|
||||||
index 791fe612..cdee4b1b 100644
|
@@ -36,6 +36,23 @@ class Distro(distros.Distro):
|
||||||
--- a/tests/unittests/test_distros/test_generic.py
|
systemd_locale_conf_fn = '/etc/locale.conf'
|
||||||
+++ b/tests/unittests/test_distros/test_generic.py
|
tz_local_fn = '/etc/localtime'
|
||||||
@@ -4,16 +4,12 @@ from cloudinit import distros
|
|
||||||
from cloudinit import util
|
|
||||||
|
|
||||||
from cloudinit.tests import helpers
|
+ __timesync_client_map = {
|
||||||
+from cloudinit.tests.helpers import mock
|
+ # Map the system_info supported values
|
||||||
|
+ 'chrony': ('chrony', 'chronyd'),
|
||||||
import os
|
+ 'isc-ntp': ('ntp', 'ntpd'),
|
||||||
import shutil
|
+ 'systemd-timesyncd': ('systemd-timesyncd', 'systemd-timesyncd'),
|
||||||
import tempfile
|
+ # Map the common names if different from system_info
|
||||||
|
+ 'chronyd': ('chrony', 'chronyd'),
|
||||||
-try:
|
+ 'ntpd': ('ntp', 'ntpd'),
|
||||||
- from unittest import mock
|
+ '/usr/lib/systemd/systemd-timesyncd':
|
||||||
-except ImportError:
|
+ ('systemd-timesyncd', 'systemd-timesyncd')
|
||||||
- import mock
|
|
||||||
-
|
|
||||||
unknown_arch_info = {
|
|
||||||
'arches': ['default'],
|
|
||||||
'failsafe': {'primary': 'http://fs-primary-default',
|
|
||||||
@@ -35,6 +31,24 @@ package_mirrors = [
|
|
||||||
unknown_arch_info
|
|
||||||
]
|
|
||||||
|
|
||||||
+timesync_user_cfg_chrony = {
|
|
||||||
+ 'system_info': {
|
|
||||||
+ 'ntp_client': 'chrony'
|
|
||||||
+ }
|
+ }
|
||||||
+}
|
+ __ntp_client_execs = [
|
||||||
|
+ 'chronyd',
|
||||||
|
+ 'ntpd',
|
||||||
|
+ '/usr/lib/systemd/systemd-timesyncd'
|
||||||
|
+ ]
|
||||||
+
|
+
|
||||||
+timesync_user_cfg_ntp = {
|
def __init__(self, name, cfg, paths):
|
||||||
+ 'system_info': {
|
distros.Distro.__init__(self, name, cfg, paths)
|
||||||
+ 'ntp_client': 'isc-ntp'
|
self._runner = helpers.Runners(paths)
|
||||||
+ }
|
@@ -145,6 +162,28 @@ class Distro(distros.Distro):
|
||||||
+}
|
host_fn = self.hostname_conf_fn
|
||||||
+
|
return (host_fn, self._read_hostname(host_fn))
|
||||||
+timesync_user_cfg_systemd = {
|
|
||||||
+ 'system_info': {
|
|
||||||
+ 'ntp_client': 'systemd-timesyncd'
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
gpmi = distros._get_package_mirror_info
|
|
||||||
gapmi = distros._get_arch_package_mirror_info
|
|
||||||
|
|
||||||
@@ -244,5 +258,82 @@ class TestGenericDistro(helpers.FilesystemMockingTestCase):
|
+ def _set_default_timesync_client(self):
|
||||||
with self.assertRaises(NotImplementedError):
|
+ """The default timesync client is dependent on the distribution."""
|
||||||
d.get_locale()
|
+ # When we get here the user has configured ntp to be enabled but
|
||||||
|
+ # no client is installed
|
||||||
+ def test_set_timesync_client_user_config_chrony_sles(self):
|
+ distro_info = util.get_linux_distro()
|
||||||
+ """Test sles distro sets proper values for chrony"""
|
+ name = distro_info[0]
|
||||||
+ cls = distros.fetch("sles")
|
+ major_ver = int(distro_info[1].split('.')[0])
|
||||||
+ d = cls("sles", timesync_user_cfg_chrony, None)
|
|
||||||
+ d.set_timesync_client()
|
|
||||||
+ self.assertEqual(d.timesync_client, 'chrony')
|
|
||||||
+ self.assertEqual(d.timesync_service_name, 'chronyd')
|
|
||||||
+
|
+
|
||||||
+ def test_set_timesync_client_user_config_ntp_sles(self):
|
+ # This is horribly complicated because of a case of
|
||||||
+ """Test sles distro sets proper values for ntp"""
|
+ # "we do not care if versions should be increasing syndrome"
|
||||||
+ cls = distros.fetch("sles")
|
+ if (
|
||||||
+ d = cls("sles", timesync_user_cfg_ntp, None)
|
+ (major_ver >= 15 and 'openSUSE' not in name) or
|
||||||
+ d.set_timesync_client()
|
+ (major_ver >= 15 and 'openSUSE' in name and major_ver != 42)
|
||||||
+ self.assertEqual(d.timesync_client, 'ntp')
|
|
||||||
+ self.assertEqual(d.timesync_service_name, 'ntpd')
|
|
||||||
+
|
|
||||||
+ def test_set_timesync_client_user_config_timesyncd_sles(self):
|
|
||||||
+ """Test sles distro sets proper values for timesyncd"""
|
|
||||||
+ cls = distros.fetch("sles")
|
|
||||||
+ d = cls("sles", timesync_user_cfg_systemd, None)
|
|
||||||
+ d.set_timesync_client()
|
|
||||||
+ self.assertEqual(d.timesync_client, 'systemd-timesyncd')
|
|
||||||
+ self.assertEqual(d.timesync_service_name, 'systemd-timesyncd')
|
|
||||||
+
|
|
||||||
+ @mock.patch("cloudinit.distros.util")
|
|
||||||
+ def test_set_timesync_client_chrony_installed_sles(self, mock_util):
|
|
||||||
+ """Test sles distro sets proper values for chrony if chrony is
|
|
||||||
+ installed"""
|
|
||||||
+ mock_util.which.side_effect = side_effect_client_is_chrony
|
|
||||||
+ cls = distros.fetch("sles")
|
|
||||||
+ d = cls("sles", {}, None)
|
|
||||||
+ d.set_timesync_client()
|
|
||||||
+ self.assertEqual(d.timesync_client, 'chrony')
|
|
||||||
+ self.assertEqual(d.timesync_service_name, 'chronyd')
|
|
||||||
+
|
|
||||||
+ @mock.patch("cloudinit.distros.util")
|
|
||||||
+ def test_set_timesync_client_ntp_installed_sles(self, mock_util):
|
|
||||||
+ """Test sles distro sets proper values for ntp if ntpd is
|
|
||||||
+ installed"""
|
|
||||||
+ mock_util.which.side_effect = side_effect_client_is_ntp
|
|
||||||
+ cls = distros.fetch("sles")
|
|
||||||
+ d = cls("sles", {}, None)
|
|
||||||
+ d.set_timesync_client()
|
|
||||||
+ self.assertEqual(d.timesync_client, 'ntp')
|
|
||||||
+ self.assertEqual(d.timesync_service_name, 'ntpd')
|
|
||||||
+
|
|
||||||
+ @mock.patch("cloudinit.distros.util")
|
|
||||||
+ def test_set_timesync_client_timesycd_installed_sles(self, mock_util):
|
|
||||||
+ """Test sles distro sets proper values for timesycd if timesyncd is
|
|
||||||
+ installed"""
|
|
||||||
+ mock_util.which.side_effect = side_effect_client_is_timesyncd
|
|
||||||
+ cls = distros.fetch("sles")
|
|
||||||
+ d = cls("sles", {}, None)
|
|
||||||
+ d.set_timesync_client()
|
|
||||||
+ self.assertEqual(d.timesync_client, 'systemd-timesyncd')
|
|
||||||
+ self.assertEqual(d.timesync_service_name, 'systemd-timesyncd')
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+def side_effect_client_is_chrony(ntp_client):
|
|
||||||
+ if 'chrony' in ntp_client:
|
|
||||||
+ return '/usr/sbin/chronyd'
|
|
||||||
+ else:
|
|
||||||
+ return False
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+def side_effect_client_is_ntp(ntp_client):
|
|
||||||
+ if 'ntp' in ntp_client:
|
|
||||||
+ return '/usr/sbin/ntpd'
|
|
||||||
+ else:
|
|
||||||
+ return False
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+def side_effect_client_is_timesyncd(ntp_client):
|
|
||||||
+ if 'timesyncd' in ntp_client:
|
|
||||||
+ return ntp_client
|
|
||||||
+ else:
|
|
||||||
+ return False
|
|
||||||
|
|
||||||
# vi: ts=4 expandtab
|
|
||||||
diff --git a/tests/unittests/test_distros/test_opensuse.py b/tests/unittests/test_distros/test_opensuse.py
|
|
||||||
index b9bb9b3e..9ed10af8 100644
|
|
||||||
--- a/tests/unittests/test_distros/test_opensuse.py
|
|
||||||
+++ b/tests/unittests/test_distros/test_opensuse.py
|
|
||||||
@@ -1,6 +1,6 @@
|
|
||||||
# This file is part of cloud-init. See LICENSE file for license information.
|
|
||||||
|
|
||||||
-from cloudinit.tests.helpers import CiTestCase
|
|
||||||
+from cloudinit.tests.helpers import CiTestCase, mock
|
|
||||||
|
|
||||||
from . import _get_distro
|
|
||||||
|
|
||||||
@@ -10,3 +10,45 @@ class TestopenSUSE(CiTestCase):
|
|
||||||
def test_get_distro(self):
|
|
||||||
distro = _get_distro("opensuse")
|
|
||||||
self.assertEqual(distro.osfamily, 'suse')
|
|
||||||
+
|
|
||||||
+ @mock.patch("cloudinit.distros.opensuse.Distro.install_packages")
|
|
||||||
+ @mock.patch("platform.linux_distribution")
|
|
||||||
+ def test_set_default_timesync_client_osl42(
|
|
||||||
+ self,
|
|
||||||
+ mock_distro,
|
|
||||||
+ mock_install
|
|
||||||
+ ):
|
|
||||||
+ mock_distro.return_value = ('openSUSE ', '42.3', 'x86_64')
|
|
||||||
+ mock_install.return_value = True
|
|
||||||
+ distro = _get_distro("opensuse")
|
|
||||||
+ distro._set_default_timesync_client()
|
|
||||||
+ self.assertEqual(distro.timesync_client, 'ntp')
|
|
||||||
+ self.assertEqual(distro.timesync_service_name, 'ntpd')
|
|
||||||
+
|
|
||||||
+ @mock.patch("cloudinit.distros.opensuse.Distro.install_packages")
|
|
||||||
+ @mock.patch("platform.linux_distribution")
|
|
||||||
+ def test_set_default_timesync_client_os13(
|
|
||||||
+ self,
|
|
||||||
+ mock_distro,
|
|
||||||
+ mock_install
|
|
||||||
+ ):
|
|
||||||
+ mock_distro.return_value = ('openSUSE ', '13.1', 'x86_64')
|
|
||||||
+ mock_install.return_value = True
|
|
||||||
+ distro = _get_distro("opensuse")
|
|
||||||
+ distro._set_default_timesync_client()
|
|
||||||
+ self.assertEqual(distro.timesync_client, 'ntp')
|
|
||||||
+ self.assertEqual(distro.timesync_service_name, 'ntpd')
|
|
||||||
+
|
|
||||||
+ @mock.patch("cloudinit.distros.opensuse.Distro.install_packages")
|
|
||||||
+ @mock.patch("platform.linux_distribution")
|
|
||||||
+ def test_set_default_timesync_client_osl15(
|
|
||||||
+ self,
|
|
||||||
+ mock_distro,
|
|
||||||
+ mock_install
|
|
||||||
+ ):
|
|
||||||
+ mock_distro.return_value = ('openSUSE ', '15.1', 'x86_64')
|
|
||||||
+ mock_install.return_value = True
|
|
||||||
+ distro = _get_distro("opensuse")
|
|
||||||
+ distro._set_default_timesync_client()
|
|
||||||
+ self.assertEqual(distro.timesync_client, 'chrony')
|
|
||||||
+ self.assertEqual(distro.timesync_service_name, 'chronyd')
|
|
||||||
diff --git a/tests/unittests/test_distros/test_sles.py b/tests/unittests/test_distros/test_sles.py
|
|
||||||
index 33e3c457..13237a27 100644
|
|
||||||
--- a/tests/unittests/test_distros/test_sles.py
|
|
||||||
+++ b/tests/unittests/test_distros/test_sles.py
|
|
||||||
@@ -1,6 +1,6 @@
|
|
||||||
# This file is part of cloud-init. See LICENSE file for license information.
|
|
||||||
|
|
||||||
-from cloudinit.tests.helpers import CiTestCase
|
|
||||||
+from cloudinit.tests.helpers import CiTestCase, mock
|
|
||||||
|
|
||||||
from . import _get_distro
|
|
||||||
|
|
||||||
@@ -10,3 +10,31 @@ class TestSLES(CiTestCase):
|
|
||||||
def test_get_distro(self):
|
|
||||||
distro = _get_distro("sles")
|
|
||||||
self.assertEqual(distro.osfamily, 'suse')
|
|
||||||
+
|
|
||||||
+ @mock.patch("cloudinit.distros.opensuse.Distro.install_packages")
|
|
||||||
+ @mock.patch("platform.linux_distribution")
|
|
||||||
+ def test_set_default_timesync_client_osl42(
|
|
||||||
+ self,
|
|
||||||
+ mock_distro,
|
|
||||||
+ mock_install
|
|
||||||
+ ):
|
|
||||||
+ mock_distro.return_value = ('SLES ', '12.3', 'x86_64')
|
|
||||||
+ mock_install.return_value = True
|
|
||||||
+ distro = _get_distro("sles")
|
|
||||||
+ distro._set_default_timesync_client()
|
|
||||||
+ self.assertEqual(distro.timesync_client, 'ntp')
|
|
||||||
+ self.assertEqual(distro.timesync_service_name, 'ntpd')
|
|
||||||
+
|
|
||||||
+ @mock.patch("cloudinit.distros.opensuse.Distro.install_packages")
|
|
||||||
+ @mock.patch("platform.linux_distribution")
|
|
||||||
+ def test_set_default_timesync_client_os13(
|
|
||||||
+ self,
|
|
||||||
+ mock_distro,
|
|
||||||
+ mock_install
|
|
||||||
+ ):
|
|
||||||
+ mock_distro.return_value = ('SLES ', '15', 'x86_64')
|
|
||||||
+ mock_install.return_value = True
|
|
||||||
+ distro = _get_distro("sles")
|
|
||||||
+ distro._set_default_timesync_client()
|
|
||||||
+ self.assertEqual(distro.timesync_client, 'chrony')
|
|
||||||
+ self.assertEqual(distro.timesync_service_name, 'chronyd')
|
|
||||||
diff --git a/tests/unittests/test_handler/test_handler_ntp.py b/tests/unittests/test_handler/test_handler_ntp.py
|
|
||||||
index 28a8455d..33fab8c8 100644
|
|
||||||
--- a/tests/unittests/test_handler/test_handler_ntp.py
|
|
||||||
+++ b/tests/unittests/test_handler/test_handler_ntp.py
|
|
||||||
@@ -10,6 +10,20 @@ import os
|
|
||||||
from os.path import dirname
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
+CHRONY_TEMPLATE = b"""\
|
|
||||||
+## template: jinja
|
|
||||||
+{% if pools %}# pools
|
|
||||||
+{% endif %}
|
|
||||||
+{% for pool in pools -%}
|
|
||||||
+pool {{pool}} iburst
|
|
||||||
+{% endfor %}
|
|
||||||
+{%- if servers %}# servers
|
|
||||||
+{% endif %}
|
|
||||||
+{% for server in servers -%}
|
|
||||||
+server {{server}} iburst
|
|
||||||
+{% endfor %}
|
|
||||||
+"""
|
|
||||||
+
|
|
||||||
NTP_TEMPLATE = b"""\
|
|
||||||
## template: jinja
|
|
||||||
servers {{servers}}
|
|
||||||
@@ -79,7 +93,7 @@ class TestNtp(FilesystemMockingTestCase):
|
|
||||||
"""When NTP_CONF exists, rename_ntp moves it."""
|
|
||||||
ntpconf = self.tmp_path("ntp.conf", self.new_root)
|
|
||||||
util.write_file(ntpconf, "")
|
|
||||||
- with mock.patch("cloudinit.config.cc_ntp.NTP_CONF", ntpconf):
|
|
||||||
+ with mock.patch("cloudinit.config.cc_ntp.NTP_CONF_FILE", ntpconf):
|
|
||||||
cc_ntp.rename_ntp_conf()
|
|
||||||
self.assertFalse(os.path.exists(ntpconf))
|
|
||||||
self.assertTrue(os.path.exists("{0}.dist".format(ntpconf)))
|
|
||||||
@@ -112,7 +126,7 @@ class TestNtp(FilesystemMockingTestCase):
|
|
||||||
"""When NTP_CONF doesn't exist rename_ntp doesn't create a file."""
|
|
||||||
ntpconf = self.tmp_path("ntp.conf", self.new_root)
|
|
||||||
self.assertFalse(os.path.exists(ntpconf))
|
|
||||||
- with mock.patch("cloudinit.config.cc_ntp.NTP_CONF", ntpconf):
|
|
||||||
+ with mock.patch("cloudinit.config.cc_ntp.NTP_CONF_FILE", ntpconf):
|
|
||||||
cc_ntp.rename_ntp_conf()
|
|
||||||
self.assertFalse(os.path.exists("{0}.dist".format(ntpconf)))
|
|
||||||
self.assertFalse(os.path.exists(ntpconf))
|
|
||||||
@@ -133,7 +147,7 @@ class TestNtp(FilesystemMockingTestCase):
|
|
||||||
# Create ntp.conf.tmpl
|
|
||||||
with open('{0}.tmpl'.format(ntp_conf), 'wb') as stream:
|
|
||||||
stream.write(NTP_TEMPLATE)
|
|
||||||
- with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf):
|
|
||||||
+ with mock.patch('cloudinit.config.cc_ntp.NTP_CONF_FILE', ntp_conf):
|
|
||||||
cc_ntp.write_ntp_config_template(cfg, mycloud, ntp_conf)
|
|
||||||
content = util.read_file_or_url('file://' + ntp_conf).contents
|
|
||||||
self.assertEqual(
|
|
||||||
@@ -159,7 +173,7 @@ class TestNtp(FilesystemMockingTestCase):
|
|
||||||
# Create ntp.conf.tmpl.<distro>
|
|
||||||
with open('{0}.{1}.tmpl'.format(ntp_conf, distro), 'wb') as stream:
|
|
||||||
stream.write(NTP_TEMPLATE)
|
|
||||||
- with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf):
|
|
||||||
+ with mock.patch('cloudinit.config.cc_ntp.NTP_CONF_FILE', ntp_conf):
|
|
||||||
cc_ntp.write_ntp_config_template(cfg, mycloud, ntp_conf)
|
|
||||||
content = util.read_file_or_url('file://' + ntp_conf).contents
|
|
||||||
self.assertEqual(
|
|
||||||
@@ -178,7 +192,7 @@ class TestNtp(FilesystemMockingTestCase):
|
|
||||||
# Create ntp.conf.tmpl
|
|
||||||
with open('{0}.tmpl'.format(ntp_conf), 'wb') as stream:
|
|
||||||
stream.write(NTP_TEMPLATE)
|
|
||||||
- with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf):
|
|
||||||
+ with mock.patch('cloudinit.config.cc_ntp.NTP_CONF_FILE', ntp_conf):
|
|
||||||
cc_ntp.write_ntp_config_template({}, mycloud, ntp_conf)
|
|
||||||
content = util.read_file_or_url('file://' + ntp_conf).contents
|
|
||||||
default_pools = [
|
|
||||||
@@ -210,7 +224,7 @@ class TestNtp(FilesystemMockingTestCase):
|
|
||||||
# Create ntp.conf.tmpl
|
|
||||||
with open('{0}.tmpl'.format(ntp_conf), 'wb') as stream:
|
|
||||||
stream.write(NTP_TEMPLATE)
|
|
||||||
- with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf):
|
|
||||||
+ with mock.patch('cloudinit.config.cc_ntp.NTP_CONF_FILE', ntp_conf):
|
|
||||||
with mock.patch.object(util, 'which', return_value=None):
|
|
||||||
cc_ntp.handle('notimportant', cfg, mycloud, None, None)
|
|
||||||
|
|
||||||
@@ -239,7 +253,10 @@ class TestNtp(FilesystemMockingTestCase):
|
|
||||||
with open(template, 'wb') as stream:
|
|
||||||
stream.write(TIMESYNCD_TEMPLATE)
|
|
||||||
|
|
||||||
- with mock.patch('cloudinit.config.cc_ntp.TIMESYNCD_CONF', tsyncd_conf):
|
|
||||||
+ with mock.patch(
|
|
||||||
+ 'cloudinit.config.cc_ntp.TIMESYNCD_CONF_FILE',
|
|
||||||
+ tsyncd_conf
|
|
||||||
+ ):
|
+ ):
|
||||||
cc_ntp.handle('notimportant', cfg, mycloud, None, None)
|
+ self.timesync_client = 'chrony'
|
||||||
|
+ self.timesync_service_name = 'chronyd'
|
||||||
content = util.read_file_or_url('file://' + tsyncd_conf).contents
|
+ self.install_packages(['chrony'])
|
||||||
@@ -267,7 +284,7 @@ class TestNtp(FilesystemMockingTestCase):
|
+ else:
|
||||||
shutil.copy(
|
+ self.timesync_client = 'ntp'
|
||||||
tmpl_file,
|
+ self.timesync_service_name = 'ntpd'
|
||||||
os.path.join(self.new_root, 'ntp.conf.%s.tmpl' % distro))
|
+ self.install_packages(['ntp'])
|
||||||
- with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf):
|
|
||||||
+ with mock.patch('cloudinit.config.cc_ntp.NTP_CONF_FILE', ntp_conf):
|
|
||||||
with mock.patch.object(util, 'which', return_value=[True]):
|
|
||||||
cc_ntp.handle('notimportant', cfg, mycloud, None, None)
|
|
||||||
|
|
||||||
@@ -300,7 +317,7 @@ class TestNtp(FilesystemMockingTestCase):
|
|
||||||
with open('{0}.tmpl'.format(ntp_conf), 'wb') as stream:
|
|
||||||
stream.write(NTP_TEMPLATE)
|
|
||||||
for valid_empty_config in valid_empty_configs:
|
|
||||||
- with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf):
|
|
||||||
+ with mock.patch('cloudinit.config.cc_ntp.NTP_CONF_FILE', ntp_conf):
|
|
||||||
cc_ntp.handle('cc_ntp', valid_empty_config, cc, None, [])
|
|
||||||
with open(ntp_conf) as stream:
|
|
||||||
content = stream.read()
|
|
||||||
@@ -323,7 +340,7 @@ class TestNtp(FilesystemMockingTestCase):
|
|
||||||
ntp_conf = os.path.join(self.new_root, 'ntp.conf')
|
|
||||||
with open('{0}.tmpl'.format(ntp_conf), 'wb') as stream:
|
|
||||||
stream.write(NTP_TEMPLATE)
|
|
||||||
- with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf):
|
|
||||||
+ with mock.patch('cloudinit.config.cc_ntp.NTP_CONF_FILE', ntp_conf):
|
|
||||||
cc_ntp.handle('cc_ntp', invalid_config, cc, None, [])
|
|
||||||
self.assertIn(
|
|
||||||
"Invalid config:\nntp.pools.0: 123 is not of type 'string'\n"
|
|
||||||
@@ -344,7 +361,7 @@ class TestNtp(FilesystemMockingTestCase):
|
|
||||||
ntp_conf = os.path.join(self.new_root, 'ntp.conf')
|
|
||||||
with open('{0}.tmpl'.format(ntp_conf), 'wb') as stream:
|
|
||||||
stream.write(NTP_TEMPLATE)
|
|
||||||
- with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf):
|
|
||||||
+ with mock.patch('cloudinit.config.cc_ntp.NTP_CONF_FILE', ntp_conf):
|
|
||||||
cc_ntp.handle('cc_ntp', invalid_config, cc, None, [])
|
|
||||||
self.assertIn(
|
|
||||||
"Invalid config:\nntp.pools: 123 is not of type 'array'\n"
|
|
||||||
@@ -366,7 +383,7 @@ class TestNtp(FilesystemMockingTestCase):
|
|
||||||
ntp_conf = os.path.join(self.new_root, 'ntp.conf')
|
|
||||||
with open('{0}.tmpl'.format(ntp_conf), 'wb') as stream:
|
|
||||||
stream.write(NTP_TEMPLATE)
|
|
||||||
- with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf):
|
|
||||||
+ with mock.patch('cloudinit.config.cc_ntp.NTP_CONF_FILE', ntp_conf):
|
|
||||||
cc_ntp.handle('cc_ntp', invalid_config, cc, None, [])
|
|
||||||
self.assertIn(
|
|
||||||
"Invalid config:\nntp: Additional properties are not allowed "
|
|
||||||
@@ -391,7 +408,7 @@ class TestNtp(FilesystemMockingTestCase):
|
|
||||||
ntp_conf = os.path.join(self.new_root, 'ntp.conf')
|
|
||||||
with open('{0}.tmpl'.format(ntp_conf), 'wb') as stream:
|
|
||||||
stream.write(NTP_TEMPLATE)
|
|
||||||
- with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf):
|
|
||||||
+ with mock.patch('cloudinit.config.cc_ntp.NTP_CONF_FILE', ntp_conf):
|
|
||||||
cc_ntp.handle('cc_ntp', invalid_config, cc, None, [])
|
|
||||||
self.assertIn(
|
|
||||||
"Invalid config:\nntp.pools: ['0.mypool.org', '0.mypool.org'] has "
|
|
||||||
@@ -421,7 +438,10 @@ class TestNtp(FilesystemMockingTestCase):
|
|
||||||
print(template)
|
|
||||||
with open(template, 'wb') as stream:
|
|
||||||
stream.write(TIMESYNCD_TEMPLATE)
|
|
||||||
- with mock.patch('cloudinit.config.cc_ntp.TIMESYNCD_CONF', tsyncd_conf):
|
|
||||||
+ with mock.patch(
|
|
||||||
+ 'cloudinit.config.cc_ntp.TIMESYNCD_CONF_FILE',
|
|
||||||
+ tsyncd_conf
|
|
||||||
+ ):
|
|
||||||
cc_ntp.write_ntp_config_template(cfg, mycloud, tsyncd_conf,
|
|
||||||
template='timesyncd.conf')
|
|
||||||
|
|
||||||
@@ -442,7 +462,7 @@ class TestNtp(FilesystemMockingTestCase):
|
|
||||||
# Create ntp.conf.tmpl
|
|
||||||
with open('{0}.tmpl'.format(ntp_conf), 'wb') as stream:
|
|
||||||
stream.write(NTP_TEMPLATE)
|
|
||||||
- with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf):
|
|
||||||
+ with mock.patch('cloudinit.config.cc_ntp.NTP_CONF_FILE', ntp_conf):
|
|
||||||
cc_ntp.write_ntp_config_template({}, mycloud, ntp_conf)
|
|
||||||
content = util.read_file_or_url('file://' + ntp_conf).contents
|
|
||||||
default_pools = [
|
|
||||||
@@ -456,5 +476,35 @@ class TestNtp(FilesystemMockingTestCase):
|
|
||||||
",".join(default_pools)),
|
|
||||||
self.logs.getvalue())
|
|
||||||
|
|
||||||
+ def test_ntp_handler_chrony(self):
|
|
||||||
+ """Test ntp handler configures chrony"""
|
|
||||||
+ distro = 'opensuse'
|
|
||||||
+ cfg = {
|
|
||||||
+ 'servers': ['192.168.2.1', '192.168.2.2'],
|
|
||||||
+ 'pools': ['0.mypool.org'],
|
|
||||||
+ }
|
|
||||||
+ mycloud = self._get_cloud(distro)
|
|
||||||
+ mycloud.timesync_client = 'chrony'
|
|
||||||
+ mycloud.timesync_service_name = 'chronyd'
|
|
||||||
+ chrony_conf = self.tmp_path("chrony.conf", self.new_root)
|
|
||||||
+ # Create chrony.conf.tmpl
|
|
||||||
+ template = '{0}.tmpl'.format(chrony_conf)
|
|
||||||
+ print(template)
|
|
||||||
+ with open(template, 'wb') as stream:
|
|
||||||
+ stream.write(CHRONY_TEMPLATE)
|
|
||||||
+ with mock.patch(
|
|
||||||
+ 'cloudinit.config.cc_ntp.CHRONY_CONF_FILE',
|
|
||||||
+ chrony_conf
|
|
||||||
+ ):
|
|
||||||
+ cc_ntp.write_ntp_config_template(cfg, mycloud, chrony_conf,
|
|
||||||
+ template='chrony.conf')
|
|
||||||
+
|
+
|
||||||
+ content = util.read_file_or_url('file://' + chrony_conf).contents
|
def _write_hostname(self, hostname, out_fn):
|
||||||
+ expected = '# pools\n'
|
if self.uses_systemd() and out_fn.endswith('/previous-hostname'):
|
||||||
+ expected += 'pool 0.mypool.org iburst\n'
|
util.write_file(out_fn, hostname)
|
||||||
+ expected += '# servers\n'
|
|
||||||
+ expected += 'server 192.168.2.1 iburst\n'
|
|
||||||
+ expected += 'server 192.168.2.2 iburst\n\n'
|
|
||||||
+ self.assertEqual(expected, content.decode())
|
|
||||||
|
|
||||||
# vi: ts=4 expandtab
|
|
||||||
--
|
|
||||||
2.13.6
|
|
||||||
|
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
From d94392bb6e54a6860c8b6ea7967e853d8e263d7a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Robert Schweikert <rjschwei@suse.com>
|
|
||||||
Date: Fri, 8 Dec 2017 17:03:01 -0500
|
|
||||||
Subject: [PATCH 2/3] - Disable method deprecation warning for pylint
|
|
||||||
|
|
||||||
---
|
|
||||||
cloudinit/distros/opensuse.py | 4 ++++
|
|
||||||
1 file changed, 4 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/cloudinit/distros/opensuse.py b/cloudinit/distros/opensuse.py
|
|
||||||
index 092d6a11..86318eae 100644
|
|
||||||
--- a/cloudinit/distros/opensuse.py
|
|
||||||
+++ b/cloudinit/distros/opensuse.py
|
|
||||||
@@ -8,6 +8,10 @@
|
|
||||||
#
|
|
||||||
# This file is part of cloud-init. See LICENSE file for license information.
|
|
||||||
|
|
||||||
+# pylint: disable=W1505
|
|
||||||
+# platform.linux_distribution is deprecated (W1505) we need to decide if
|
|
||||||
+# cloud-init will implement it's own or add a new dependency on the
|
|
||||||
+# distro module
|
|
||||||
import platform
|
|
||||||
|
|
||||||
from cloudinit import distros
|
|
||||||
--
|
|
||||||
2.13.6
|
|
||||||
|
|
@ -1,67 +1,6 @@
|
|||||||
From 42cb1841035befa5b5823b3321c8fe92f2cb9087 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Robert Schweikert <rjschwei@suse.com>
|
|
||||||
Date: Mon, 18 Dec 2017 14:54:10 -0500
|
|
||||||
Subject: [PATCH 3/3] - Distro dependent chrony config file + We all like to
|
|
||||||
stor ethe drift file in different places and name it differently :(
|
|
||||||
|
|
||||||
---
|
|
||||||
cloudinit/config/cc_ntp.py | 8 +++++--
|
|
||||||
...{chrony.conf.tmpl => chrony.conf.opensuse.tmpl} | 0
|
|
||||||
templates/chrony.conf.sles.tmpl | 25 ++++++++++++++++++++++
|
|
||||||
3 files changed, 31 insertions(+), 2 deletions(-)
|
|
||||||
rename templates/{chrony.conf.tmpl => chrony.conf.opensuse.tmpl} (100%)
|
|
||||||
create mode 100644 templates/chrony.conf.sles.tmpl
|
|
||||||
|
|
||||||
diff --git a/cloudinit/config/cc_ntp.py b/cloudinit/config/cc_ntp.py
|
|
||||||
index 2f662a9e..1db648bc 100644
|
|
||||||
--- a/cloudinit/config/cc_ntp.py
|
|
||||||
+++ b/cloudinit/config/cc_ntp.py
|
|
||||||
@@ -50,6 +50,7 @@ schema = {
|
|
||||||
'examples': [
|
|
||||||
dedent("""\
|
|
||||||
ntp:
|
|
||||||
+ enabled: true
|
|
||||||
pools: [0.int.pool.ntp.org, 1.int.pool.ntp.org, ntp.myorg.org]
|
|
||||||
servers:
|
|
||||||
- ntp.server.local
|
|
||||||
@@ -61,6 +62,9 @@ schema = {
|
|
||||||
'ntp': {
|
|
||||||
'type': ['object', 'null'],
|
|
||||||
'properties': {
|
|
||||||
+ 'enabled': {
|
|
||||||
+ "type": "boolean"
|
|
||||||
+ },
|
|
||||||
'pools': {
|
|
||||||
'type': 'array',
|
|
||||||
'items': {
|
|
||||||
@@ -109,7 +113,7 @@ def handle(name, cfg, cloud, log, _args):
|
|
||||||
if not isinstance(ntp_cfg, (dict)):
|
|
||||||
raise RuntimeError(("'ntp' key existed in config,"
|
|
||||||
" but not a dictionary type,"
|
|
||||||
- " is a %s %instead"), type_utils.obj_name(ntp_cfg))
|
|
||||||
+ " is a %s instead"), type_utils.obj_name(ntp_cfg))
|
|
||||||
|
|
||||||
if ntp_cfg.get('enabled') and ntp_cfg.get('enabled') == 'true':
|
|
||||||
cloud.distro.set_timesync_client()
|
|
||||||
@@ -129,7 +133,7 @@ def handle(name, cfg, cloud, log, _args):
|
|
||||||
template_name = 'timesyncd.conf'
|
|
||||||
elif client_name == 'chrony':
|
|
||||||
confpath = CHRONY_CONF_FILE
|
|
||||||
- template_name = 'chrony.conf'
|
|
||||||
+ template_name = 'chrony.conf.%s' % cloud.distro.name
|
|
||||||
else:
|
|
||||||
if ntp_installable():
|
|
||||||
service_name = 'ntp'
|
|
||||||
diff --git a/templates/chrony.conf.tmpl b/templates/chrony.conf.opensuse.tmpl
|
|
||||||
similarity index 100%
|
|
||||||
rename from templates/chrony.conf.tmpl
|
|
||||||
rename to templates/chrony.conf.opensuse.tmpl
|
|
||||||
diff --git a/templates/chrony.conf.sles.tmpl b/templates/chrony.conf.sles.tmpl
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..38e84d85
|
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/templates/chrony.conf.sles.tmpl
|
+++ templates/chrony.conf.sles.tmpl
|
||||||
@@ -0,0 +1,25 @@
|
@@ -0,0 +1,24 @@
|
||||||
+## template:jinja
|
+## template:jinja
|
||||||
+# cloud-init generated file
|
+# cloud-init generated file
|
||||||
+# See chrony.conf(5)
|
+# See chrony.conf(5)
|
||||||
@ -86,7 +25,30 @@ index 00000000..38e84d85
|
|||||||
+
|
+
|
||||||
+# Enable kernel synchronization of the real-time clock (RTC).
|
+# Enable kernel synchronization of the real-time clock (RTC).
|
||||||
+rtcsync
|
+rtcsync
|
||||||
|
--- /dev/null
|
||||||
|
+++ templates/chrony.conf.opensuse.tmpl
|
||||||
|
@@ -0,0 +1,24 @@
|
||||||
|
+## template:jinja
|
||||||
|
+# cloud-init generated file
|
||||||
|
+# See chrony.conf(5)
|
||||||
+
|
+
|
||||||
--
|
+{% if pools %}# pools
|
||||||
2.13.6
|
+{% endif %}
|
||||||
|
+{% for pool in pools -%}
|
||||||
|
+pool {{pool}} iburst
|
||||||
|
+{% endfor %}
|
||||||
|
+{%- if servers %}# servers
|
||||||
|
+{% endif %}
|
||||||
|
+{% for server in servers -%}
|
||||||
|
+server {{server}} iburst
|
||||||
|
+{% endfor %}
|
||||||
|
+
|
||||||
|
+# Record the rate at which the the system clock gains/losses time
|
||||||
|
+driftfile /var/lib/chrony/drift
|
||||||
|
+
|
||||||
|
+# Allow the system clock to be stepped in the first three updates
|
||||||
|
+# if its offset is larger than 1 second.
|
||||||
|
+makestep 1.0 3
|
||||||
|
+
|
||||||
|
+# Enable kernel synchronization of the real-time clock (RTC).
|
||||||
|
+rtcsync
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:f00338767a8877c8d72fe64a78d3897da822b3c1f47779ae31adc4815275594f
|
|
||||||
size 810821
|
|
3
cloud-init-18.1.tar.gz
Normal file
3
cloud-init-18.1.tar.gz
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:49d8b7b56adbc6b8bc2aac966954c6c192382ea0500497577f8867e7e25e1ae6
|
||||||
|
size 833394
|
@ -1,25 +1,22 @@
|
|||||||
--- /dev/null
|
--- cloudinit/tests/test_util.py.orig
|
||||||
+++ cloudinit/tests/test_util.py
|
+++ cloudinit/tests/test_util.py
|
||||||
@@ -0,0 +1,129 @@
|
@@ -3,10 +3,12 @@
|
||||||
+# This file is part of cloud-init. See LICENSE file for license information.
|
"""Tests for cloudinit.util"""
|
||||||
+
|
|
||||||
+"""Tests for cloudinit.util"""
|
import logging
|
||||||
+
|
|
||||||
+import logging
|
|
||||||
+import platform
|
+import platform
|
||||||
+
|
|
||||||
+import cloudinit.util as util
|
import cloudinit.util as util
|
||||||
+
|
|
||||||
+from cloudinit.tests.helpers import CiTestCase, mock
|
from cloudinit.tests.helpers import CiTestCase, mock
|
||||||
+from textwrap import dedent
|
+from textwrap import dedent
|
||||||
+
|
|
||||||
+LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
+
|
|
||||||
+MOUNT_INFO = [
|
@@ -15,6 +17,29 @@ MOUNT_INFO = [
|
||||||
+ '68 0 8:3 / / ro,relatime shared:1 - btrfs /dev/sda1 ro,attr2,inode64',
|
'153 68 254:0 / /home rw,relatime shared:101 - xfs /dev/sda2 rw,attr2'
|
||||||
+ '153 68 254:0 / /home rw,relatime shared:101 - xfs /dev/sda2 rw,attr2'
|
]
|
||||||
+]
|
|
||||||
+
|
|
||||||
+OS_RELEASE_SLES = dedent("""\
|
+OS_RELEASE_SLES = dedent("""\
|
||||||
+NAME="SLES"\n
|
+NAME="SLES"\n
|
||||||
+VERSION="12-SP3"\n
|
+VERSION="12-SP3"\n
|
||||||
@ -43,35 +40,13 @@
|
|||||||
+UBUNTU_CODENAME=xenial\n
|
+UBUNTU_CODENAME=xenial\n
|
||||||
+""")
|
+""")
|
||||||
+
|
+
|
||||||
+
|
|
||||||
+class TestUtil(CiTestCase):
|
class TestUtil(CiTestCase):
|
||||||
+
|
|
||||||
+ def test_parse_mount_info_no_opts_no_arg(self):
|
@@ -44,3 +69,61 @@ class TestUtil(CiTestCase):
|
||||||
+ result = util.parse_mount_info('/home', MOUNT_INFO, LOG)
|
m_mount_info.return_value = ('/dev/sda1', 'btrfs', '/', 'ro,relatime')
|
||||||
+ self.assertEqual(('/dev/sda2', 'xfs', '/home'), result)
|
is_rw = util.mount_is_read_write('/')
|
||||||
+
|
self.assertEqual(is_rw, False)
|
||||||
+ def test_parse_mount_info_no_opts_arg(self):
|
|
||||||
+ result = util.parse_mount_info('/home', MOUNT_INFO, LOG, False)
|
|
||||||
+ self.assertEqual(('/dev/sda2', 'xfs', '/home'), result)
|
|
||||||
+
|
|
||||||
+ def test_parse_mount_info_with_opts(self):
|
|
||||||
+ result = util.parse_mount_info('/', MOUNT_INFO, LOG, True)
|
|
||||||
+ self.assertEqual(
|
|
||||||
+ ('/dev/sda1', 'btrfs', '/', 'ro,relatime'),
|
|
||||||
+ result
|
|
||||||
+ )
|
|
||||||
+
|
|
||||||
+ @mock.patch('cloudinit.util.get_mount_info')
|
|
||||||
+ def test_mount_is_rw(self, m_mount_info):
|
|
||||||
+ m_mount_info.return_value = ('/dev/sda1', 'btrfs', '/', 'rw,relatime')
|
|
||||||
+ is_rw = util.mount_is_read_write('/')
|
|
||||||
+ self.assertEqual(is_rw, True)
|
|
||||||
+
|
|
||||||
+ @mock.patch('cloudinit.util.get_mount_info')
|
|
||||||
+ def test_mount_is_ro(self, m_mount_info):
|
|
||||||
+ m_mount_info.return_value = ('/dev/sda1', 'btrfs', '/', 'ro,relatime')
|
|
||||||
+ is_rw = util.mount_is_read_write('/')
|
|
||||||
+ self.assertEqual(is_rw, False)
|
|
||||||
+
|
+
|
||||||
+ @mock.patch('os.path.exists')
|
+ @mock.patch('os.path.exists')
|
||||||
+ @mock.patch('cloudinit.util.load_file')
|
+ @mock.patch('cloudinit.util.load_file')
|
||||||
@ -132,7 +107,7 @@
|
|||||||
+ return 1
|
+ return 1
|
||||||
--- cloudinit/util.py.orig
|
--- cloudinit/util.py.orig
|
||||||
+++ cloudinit/util.py
|
+++ cloudinit/util.py
|
||||||
@@ -570,6 +570,43 @@ def get_cfg_option_str(yobj, key, defaul
|
@@ -576,6 +576,43 @@ def get_cfg_option_str(yobj, key, defaul
|
||||||
def get_cfg_option_int(yobj, key, default=0):
|
def get_cfg_option_int(yobj, key, default=0):
|
||||||
return int(get_cfg_option_str(yobj, key, default=default))
|
return int(get_cfg_option_str(yobj, key, default=default))
|
||||||
|
|
||||||
@ -176,7 +151,7 @@
|
|||||||
|
|
||||||
def system_info():
|
def system_info():
|
||||||
info = {
|
info = {
|
||||||
@@ -578,19 +615,19 @@ def system_info():
|
@@ -584,19 +621,19 @@ def system_info():
|
||||||
'release': platform.release(),
|
'release': platform.release(),
|
||||||
'python': platform.python_version(),
|
'python': platform.python_version(),
|
||||||
'uname': platform.uname(),
|
'uname': platform.uname(),
|
||||||
@ -199,82 +174,9 @@
|
|||||||
var = 'suse'
|
var = 'suse'
|
||||||
else:
|
else:
|
||||||
var = 'linux'
|
var = 'linux'
|
||||||
@@ -2053,7 +2090,7 @@ def expand_package_list(version_fmt, pkg
|
|
||||||
return pkglist
|
|
||||||
|
|
||||||
|
|
||||||
-def parse_mount_info(path, mountinfo_lines, log=LOG):
|
|
||||||
+def parse_mount_info(path, mountinfo_lines, log=LOG, get_mnt_opts=False):
|
|
||||||
"""Return the mount information for PATH given the lines from
|
|
||||||
/proc/$$/mountinfo."""
|
|
||||||
|
|
||||||
@@ -2115,11 +2152,16 @@ def parse_mount_info(path, mountinfo_lin
|
|
||||||
|
|
||||||
match_mount_point = mount_point
|
|
||||||
match_mount_point_elements = mount_point_elements
|
|
||||||
+ mount_options = parts[5]
|
|
||||||
|
|
||||||
- if devpth and fs_type and match_mount_point:
|
|
||||||
- return (devpth, fs_type, match_mount_point)
|
|
||||||
+ if get_mnt_opts:
|
|
||||||
+ if devpth and fs_type and match_mount_point and mount_options:
|
|
||||||
+ return (devpth, fs_type, match_mount_point, mount_options)
|
|
||||||
else:
|
|
||||||
- return None
|
|
||||||
+ if devpth and fs_type and match_mount_point:
|
|
||||||
+ return (devpth, fs_type, match_mount_point)
|
|
||||||
+
|
|
||||||
+ return None
|
|
||||||
|
|
||||||
|
|
||||||
def parse_mtab(path):
|
|
||||||
@@ -2189,7 +2231,7 @@ def parse_mount(path):
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
-def get_mount_info(path, log=LOG):
|
|
||||||
+def get_mount_info(path, log=LOG, get_mnt_opts=False):
|
|
||||||
# Use /proc/$$/mountinfo to find the device where path is mounted.
|
|
||||||
# This is done because with a btrfs filesystem using os.stat(path)
|
|
||||||
# does not return the ID of the device.
|
|
||||||
@@ -2221,7 +2263,7 @@ def get_mount_info(path, log=LOG):
|
|
||||||
mountinfo_path = '/proc/%s/mountinfo' % os.getpid()
|
|
||||||
if os.path.exists(mountinfo_path):
|
|
||||||
lines = load_file(mountinfo_path).splitlines()
|
|
||||||
- return parse_mount_info(path, lines, log)
|
|
||||||
+ return parse_mount_info(path, lines, log, get_mnt_opts)
|
|
||||||
elif os.path.exists("/etc/mtab"):
|
|
||||||
return parse_mtab(path)
|
|
||||||
else:
|
|
||||||
@@ -2329,7 +2371,8 @@ def pathprefix2dict(base, required=None,
|
|
||||||
missing.append(f)
|
|
||||||
|
|
||||||
if len(missing):
|
|
||||||
- raise ValueError("Missing required files: %s", ','.join(missing))
|
|
||||||
+ raise ValueError(
|
|
||||||
+ 'Missing required files: {files}'.format(files=','.join(missing)))
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
@@ -2606,4 +2649,10 @@ def wait_for_files(flist, maxwait, naple
|
|
||||||
return need
|
|
||||||
|
|
||||||
|
|
||||||
+def mount_is_read_write(mount_point):
|
|
||||||
+ """Check whether the given mount point is mounted rw"""
|
|
||||||
+ result = get_mount_info(mount_point, get_mnt_opts=True)
|
|
||||||
+ mount_opts = result[-1].split(',')
|
|
||||||
+ return mount_opts[0] == 'rw'
|
|
||||||
+
|
|
||||||
# vi: ts=4 expandtab
|
|
||||||
--- setup.py.orig
|
--- setup.py.orig
|
||||||
+++ setup.py
|
+++ setup.py
|
||||||
@@ -1,3 +1,4 @@
|
@@ -25,7 +25,7 @@ from distutils.errors import DistutilsAr
|
||||||
+
|
|
||||||
# Copyright (C) 2009 Canonical Ltd.
|
|
||||||
# Copyright (C) 2012 Yahoo! Inc.
|
|
||||||
#
|
|
||||||
@@ -25,7 +26,7 @@ from distutils.errors import DistutilsAr
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
RENDERED_TMPD_PREFIX = "RENDERED_TEMPD"
|
RENDERED_TMPD_PREFIX = "RENDERED_TEMPD"
|
||||||
@ -283,7 +185,7 @@
|
|||||||
|
|
||||||
def is_f(p):
|
def is_f(p):
|
||||||
return os.path.isfile(p)
|
return os.path.isfile(p)
|
||||||
@@ -114,10 +115,20 @@ def render_tmpl(template):
|
@@ -114,10 +114,20 @@ def render_tmpl(template):
|
||||||
atexit.register(shutil.rmtree, tmpd)
|
atexit.register(shutil.rmtree, tmpd)
|
||||||
bname = os.path.basename(template).rstrip(tmpl_ext)
|
bname = os.path.basename(template).rstrip(tmpl_ext)
|
||||||
fpath = os.path.join(tmpd, bname)
|
fpath = os.path.join(tmpd, bname)
|
||||||
@ -305,7 +207,7 @@
|
|||||||
|
|
||||||
INITSYS_FILES = {
|
INITSYS_FILES = {
|
||||||
'sysvinit': [f for f in glob('sysvinit/redhat/*') if is_f(f)],
|
'sysvinit': [f for f in glob('sysvinit/redhat/*') if is_f(f)],
|
||||||
@@ -227,6 +238,19 @@ if not in_virtualenv():
|
@@ -227,6 +237,19 @@ if not in_virtualenv():
|
||||||
for k in INITSYS_ROOTS.keys():
|
for k in INITSYS_ROOTS.keys():
|
||||||
INITSYS_ROOTS[k] = "/" + INITSYS_ROOTS[k]
|
INITSYS_ROOTS[k] = "/" + INITSYS_ROOTS[k]
|
||||||
|
|
||||||
@ -325,7 +227,7 @@
|
|||||||
data_files = [
|
data_files = [
|
||||||
(ETC + '/cloud', [render_tmpl("config/cloud.cfg.tmpl")]),
|
(ETC + '/cloud', [render_tmpl("config/cloud.cfg.tmpl")]),
|
||||||
(ETC + '/cloud/cloud.cfg.d', glob('config/cloud.cfg.d/*')),
|
(ETC + '/cloud/cloud.cfg.d', glob('config/cloud.cfg.d/*')),
|
||||||
@@ -259,7 +283,7 @@ requirements = read_requires()
|
@@ -259,7 +282,7 @@ requirements = read_requires()
|
||||||
setuptools.setup(
|
setuptools.setup(
|
||||||
name='cloud-init',
|
name='cloud-init',
|
||||||
version=get_version(),
|
version=get_version(),
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
Index: cloudinit/util.py
|
|
||||||
===================================================================
|
|
||||||
--- cloudinit/util.py.orig
|
--- cloudinit/util.py.orig
|
||||||
+++ cloudinit/util.py
|
+++ cloudinit/util.py
|
||||||
@@ -35,6 +35,7 @@ import time
|
@@ -35,6 +35,7 @@ import time
|
||||||
@ -10,13 +8,13 @@ Index: cloudinit/util.py
|
|||||||
from six.moves.urllib import parse as urlparse
|
from six.moves.urllib import parse as urlparse
|
||||||
|
|
||||||
import six
|
import six
|
||||||
@@ -1858,7 +1859,8 @@ def subp(args, data=None, rcs=None, env=
|
@@ -1868,7 +1869,8 @@ def subp(args, data=None, rcs=None, env=
|
||||||
|
try:
|
||||||
sp = subprocess.Popen(args, stdout=stdout,
|
sp = subprocess.Popen(args, stdout=stdout,
|
||||||
stderr=stderr, stdin=stdin,
|
stderr=stderr, stdin=stdin,
|
||||||
- env=env, shell=shell)
|
- env=env, shell=shell)
|
||||||
+ env=env, shell=shell,
|
+ env=env, shell=shell,
|
||||||
+ preexec_fn=lambda: signal(SIGPIPE, SIG_DFL))
|
+ preexec_fn=lambda: signal(SIGPIPE, SIG_DFL))
|
||||||
(out, err) = sp.communicate(data)
|
(out, err) = sp.communicate(data)
|
||||||
|
except OSError as e:
|
||||||
# Just ensure blank instead of none.
|
raise ProcessExecutionError(
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
--- cloudinit/config/cc_resizefs.py
|
|
||||||
+++ cloudinit/config/cc_resizefs.py 2017/11/27 11:55:37
|
|
||||||
@@ -59,7 +59,16 @@
|
|
||||||
|
|
||||||
|
|
||||||
def _resize_btrfs(mount_point, devpth):
|
|
||||||
- return ('btrfs', 'filesystem', 'resize', 'max', mount_point)
|
|
||||||
+# That btrfs utilities are using a path and not a device is bad,
|
|
||||||
+# because the subvolume specified by '/' could be read-only
|
|
||||||
+# and btrfs will wrongly fail. Correct fix would be to mount the
|
|
||||||
+# real root of the filesystem (subvolid=5) and resize that. But
|
|
||||||
+# using /.snapshots as workaround is Ok, too, since this is
|
|
||||||
+# normally writeable.
|
|
||||||
+ if mount_point == '/' and os.path.isdir("/.snapshots"):
|
|
||||||
+ return ('btrfs', 'filesystem', 'resize', 'max', '/.snapshots')
|
|
||||||
+ else:
|
|
||||||
+ return ('btrfs', 'filesystem', 'resize', 'max', mount_point)
|
|
||||||
|
|
||||||
|
|
||||||
def _resize_ext(mount_point, devpth):
|
|
@ -1,3 +1,67 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Mar 21 22:27:40 UTC 2018 - rjschwei@suse.com
|
||||||
|
|
||||||
|
- Update to version 18.1 (bsc#1085787, bsc#1084749)
|
||||||
|
+ Forward port cloud-init-python2-sigpipe.patch
|
||||||
|
+ Forward port 0003-Distro-dependent-chrony-config-file.patch
|
||||||
|
partial integration into 0001-Support-chrony-configuration-lp-1731619.patch
|
||||||
|
+ Forward port cloud-init-no-python-linux-dist.patch
|
||||||
|
+ Remove 0002-Disable-method-deprecation-warning-for-pylint.patch
|
||||||
|
use new cloud-init internal distro detection code
|
||||||
|
+ Remove cloud-init-resize-ro-btrfs.patch included upstream
|
||||||
|
+ Remove 0001-Set-syslog_fix_perms-for-SUSE-distro-addresses-bsc-1.patch
|
||||||
|
included upstream
|
||||||
|
+ OVF: Fix VMware support for 64-bit platforms. [Sankar Tanguturi]
|
||||||
|
+ ds-identify: Fix searching for iso9660 OVF cdroms. (LP: #1749980)
|
||||||
|
+ SUSE: Fix groups used for ownership of cloud-init.log [Robert Schweikert]
|
||||||
|
+ ds-identify: check /writable/system-data/ for nocloud seed.
|
||||||
|
(LP: #1747070)
|
||||||
|
+ tests: run nosetests in cloudinit/ directory, fix py26 fallout.
|
||||||
|
+ tools: run-centos: git clone rather than tar.
|
||||||
|
+ tests: add support for logs with lxd from snap and future lxd 3.
|
||||||
|
(LP: #1745663)
|
||||||
|
+ EC2: Fix get_instance_id called against cached datasource pickle.
|
||||||
|
(LP: #1748354)
|
||||||
|
+ cli: fix cloud-init status to report running when before result.json
|
||||||
|
(LP: #1747965)
|
||||||
|
+ net: accept network-config in netplan format for renaming interfaces
|
||||||
|
(LP: #1709715)
|
||||||
|
+ Fix ssh keys validation in ssh_util [Tatiana Kholkina]
|
||||||
|
+ docs: Update RTD content for cloud-init subcommands.
|
||||||
|
+ OVF: Extend well-known labels to include OVFENV. (LP: #1698669)
|
||||||
|
+ Fix potential cases of uninitialized variables. (LP: #1744796)
|
||||||
|
+ tests: Collect script output as binary, collect systemd journal, fix lxd.
|
||||||
|
+ HACKING.rst: mention setting user name and email via git config.
|
||||||
|
+ Azure VM Preprovisioning support. [Douglas Jordan] (LP: #1734991)
|
||||||
|
+ tools/read-version: Fix read-version when in a git worktree.
|
||||||
|
+ docs: Fix typos in docs and one debug message. [Florian Grignon]
|
||||||
|
+ btrfs: support resizing if root is mounted ro.
|
||||||
|
[Robert Schweikert] (LP: #1734787)
|
||||||
|
+ OpenNebula: Improve network configuration support.
|
||||||
|
[Akihiko Ota] (LP: #1719157, #1716397, #1736750)
|
||||||
|
+ tests: Fix EC2 Platform to return console output as bytes.
|
||||||
|
+ tests: Fix attempted use of /run in a test case.
|
||||||
|
+ GCE: Improvements and changes to ssh key behavior for default user.
|
||||||
|
[Max Illfelder] (LP: #1670456, #1707033, #1707037, #1707039)
|
||||||
|
+ subp: make ProcessExecutionError have expected types in stderr, stdout.
|
||||||
|
+ tests: when querying ntp server, do not do dns resolution.
|
||||||
|
+ Recognize uppercase vfat disk labels [James Penick] (LP: #1598783)
|
||||||
|
+ tests: remove zesty as supported OS to test [Joshua Powers]
|
||||||
|
+ Do not log warning on config files that represent None. (LP: #1742479)
|
||||||
|
+ tests: Use git hash pip dependency format for pylxd.
|
||||||
|
+ tests: add integration requirements text file [Joshua Powers]
|
||||||
|
+ MAAS: add check_instance_id based off oauth tokens. (LP: #1712680)
|
||||||
|
+ tests: update apt sources list test [Joshua Powers]
|
||||||
|
+ tests: clean up image properties [Joshua Powers]
|
||||||
|
+ tests: rename test ssh keys to avoid appearance of leaking private keys.
|
||||||
|
[Joshua Powers]
|
||||||
|
+ tests: Enable AWS EC2 Integration Testing [Joshua Powers]
|
||||||
|
+ cli: cloud-init clean handles symlinks (LP: #1741093)
|
||||||
|
+ SUSE: Add a basic test of network config rendering. [Robert Schweikert]
|
||||||
|
+ Azure: Only bounce network when necessary. (LP: #1722668)
|
||||||
|
+ lint: Fix lints seen by pylint version 1.8.1.
|
||||||
|
+ cli: Fix error in cloud-init modules --mode=init. (LP: #1736600)
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Fri Feb 16 13:23:00 UTC 2018 - dmueller@suse.com
|
Fri Feb 16 13:23:00 UTC 2018 - dmueller@suse.com
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
%global configver 0.7
|
%global configver 0.7
|
||||||
|
|
||||||
Name: cloud-init
|
Name: cloud-init
|
||||||
Version: 17.2
|
Version: 18.1
|
||||||
Release: 0
|
Release: 0
|
||||||
License: GPL-3.0 and AGPL-3.0
|
License: GPL-3.0 and AGPL-3.0
|
||||||
Summary: Cloud node initialization tool
|
Summary: Cloud node initialization tool
|
||||||
@ -37,15 +37,11 @@ Patch20: cloud-init-python2-sigpipe.patch
|
|||||||
Patch27: cloud-init-sysconfig-netpathfix.patch
|
Patch27: cloud-init-sysconfig-netpathfix.patch
|
||||||
Patch29: datasourceLocalDisk.patch
|
Patch29: datasourceLocalDisk.patch
|
||||||
Patch34: cloud-init-tests-set-exec.patch
|
Patch34: cloud-init-tests-set-exec.patch
|
||||||
# FIXME cloud-init-resize-ro-btrfs.patch
|
|
||||||
# proposed for upstream merge (lp#1734787)
|
|
||||||
Patch36: cloud-init-resize-ro-btrfs.patch
|
|
||||||
# FIXME chrony support upstream
|
# FIXME chrony support upstream
|
||||||
# These patches represent a working appraoch to supporting chrony
|
# These patches represent a working appraoch to supporting chrony
|
||||||
# Upstream is seeking a significant re-write which is not likely to happen
|
# Upstream is seeking a significant re-write which is not likely to happen
|
||||||
# before we need chrony support
|
# before we need chrony support
|
||||||
Patch37: 0001-Support-chrony-configuration-lp-1731619.patch
|
Patch37: 0001-Support-chrony-configuration-lp-1731619.patch
|
||||||
Patch38: 0002-Disable-method-deprecation-warning-for-pylint.patch
|
|
||||||
Patch39: 0003-Distro-dependent-chrony-config-file.patch
|
Patch39: 0003-Distro-dependent-chrony-config-file.patch
|
||||||
# FIXME switch to iproute2 tools
|
# FIXME switch to iproute2 tools
|
||||||
# Proposed for merging upstream
|
# Proposed for merging upstream
|
||||||
@ -55,9 +51,6 @@ Patch40: 0001-switch-to-using-iproute2-tools.patch
|
|||||||
Patch41: cloud-init-no-python-linux-dist.patch
|
Patch41: cloud-init-no-python-linux-dist.patch
|
||||||
# Disable OVF tests
|
# Disable OVF tests
|
||||||
Patch42: cloud-init-skip-ovf-tests.patch
|
Patch42: cloud-init-skip-ovf-tests.patch
|
||||||
# FIXME do not use the default user:groups for log file permission settings
|
|
||||||
# Proposed for merging upstream
|
|
||||||
Patch43: 0001-Set-syslog_fix_perms-for-SUSE-distro-addresses-bsc-1.patch
|
|
||||||
BuildRequires: fdupes
|
BuildRequires: fdupes
|
||||||
BuildRequires: filesystem
|
BuildRequires: filesystem
|
||||||
# pkg-config is needed to find correct systemd unit dir
|
# pkg-config is needed to find correct systemd unit dir
|
||||||
@ -196,14 +189,11 @@ Documentation and examples for cloud-init tools
|
|||||||
%patch27
|
%patch27
|
||||||
%patch29 -p0
|
%patch29 -p0
|
||||||
%patch34
|
%patch34
|
||||||
%patch36
|
%patch37
|
||||||
%patch37 -p1
|
|
||||||
%patch38 -p1
|
|
||||||
%patch39 -p1
|
%patch39 -p1
|
||||||
%patch40 -p1
|
%patch40 -p1
|
||||||
%patch41
|
%patch41
|
||||||
%patch42
|
%patch42
|
||||||
%patch43 -p1
|
|
||||||
|
|
||||||
%build
|
%build
|
||||||
%if 0%{?suse_version} && 0%{?suse_version} <= 1315
|
%if 0%{?suse_version} && 0%{?suse_version} <= 1315
|
||||||
|
Loading…
Reference in New Issue
Block a user