SHA256
1
0
forked from pool/cloud-init
cloud-init/cloud-init-no-python-linux-dist.patch
Robert Schweikert fb31094f97 - Update to version 17.2 (boo#1069635, bsc#1072811)
+ Add cloud-init-skip-ovf-tests.patch
  + Add cloud-init-no-python-linux-dist.patch
  + Add 0001-switch-to-using-iproute2-tools.patch
  + Add 0001-Support-chrony-configuration-lp-1731619.patch
  + Add 0002-Disable-method-deprecation-warning-for-pylint.patch
  + Add 0003-Distro-dependent-chrony-config-file.patch
  + removed cloud-init-add-variant-cloudcfg.patch replaced by
    cloud-init-no-python-linux-dist.patch
  + removed zypp_add_repos.diff included upstream
  + removed zypp_add_repo_test.patch included upstream
  + removed cloud-init-hosts-template.patch included upstream
  + removed cloud-init-more-tasks.patch included upstream
  + removed cloud-init-final-no-apt.patch included upstream
  + removed cloud-init-ntp-conf-suse.patch included upstream
  + removed cloud-init-break-cycle-local-service.patch included upstream
  + removed cloud-init-reproduce-build.patch included upstream
  + For the complete changelog see https://launchpad.net/cloud-init/trunk/17.2

OBS-URL: https://build.opensuse.org/package/show/Cloud:Tools/cloud-init?expand=0&rev=105
2018-01-29 21:11:23 +00:00

337 lines
12 KiB
Diff

--- /dev/null
+++ cloudinit/tests/test_util.py
@@ -0,0 +1,129 @@
+# This file is part of cloud-init. See LICENSE file for license information.
+
+"""Tests for cloudinit.util"""
+
+import logging
+import platform
+
+import cloudinit.util as util
+
+from cloudinit.tests.helpers import CiTestCase, mock
+from textwrap import dedent
+
+LOG = logging.getLogger(__name__)
+
+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'
+]
+
+OS_RELEASE_SLES = dedent("""\
+NAME="SLES"\n
+VERSION="12-SP3"\n
+VERSION_ID="12.3"\n
+PRETTY_NAME="SUSE Linux Enterprise Server 12 SP3"\n
+ID="sles"\nANSI_COLOR="0;32"\n
+CPE_NAME="cpe:/o:suse:sles:12:sp3"\n
+""")
+
+OS_RELEASE_UBUNTU = dedent("""\
+NAME="Ubuntu"\n
+VERSION="16.04.3 LTS (Xenial Xerus)"\n
+ID=ubuntu\n
+ID_LIKE=debian\n
+PRETTY_NAME="Ubuntu 16.04.3 LTS"\n
+VERSION_ID="16.04"\n
+HOME_URL="http://www.ubuntu.com/"\n
+SUPPORT_URL="http://help.ubuntu.com/"\n
+BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"\n
+VERSION_CODENAME=xenial\n
+UBUNTU_CODENAME=xenial\n
+""")
+
+
+class TestUtil(CiTestCase):
+
+ def test_parse_mount_info_no_opts_no_arg(self):
+ result = util.parse_mount_info('/home', MOUNT_INFO, LOG)
+ self.assertEqual(('/dev/sda2', 'xfs', '/home'), result)
+
+ 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('cloudinit.util.load_file')
+ def test_get_linux_distro_quoted_name(self, m_os_release, m_path_exists):
+ m_os_release.return_value = OS_RELEASE_SLES
+ m_path_exists.side_effect = os_release_exists
+ dist = util.get_linux_distro()
+ self.assertEqual(('sles', '12.3', platform.machine()), dist)
+
+ @mock.patch('os.path.exists')
+ @mock.patch('cloudinit.util.load_file')
+ def test_get_linux_distro_bare_name(self, m_os_release, m_path_exists):
+ m_os_release.return_value = OS_RELEASE_UBUNTU
+ m_path_exists.side_effect = os_release_exists
+ dist = util.get_linux_distro()
+ self.assertEqual(('ubuntu', '16.04', platform.machine()), dist)
+
+ @mock.patch('os.path.exists')
+ @mock.patch('platform.dist')
+ def test_get_linux_distro_no_data(self, m_platform_dist, m_path_exists):
+ m_platform_dist.return_value = ('', '', '')
+ m_path_exists.return_value = 0
+ dist = util.get_linux_distro()
+ self.assertEqual(('', '', ''), dist)
+
+ @mock.patch('os.path.exists')
+ @mock.patch('platform.dist')
+ def test_get_linux_distro_no_impl(self, m_platform_dist, m_path_exists):
+ m_platform_dist.side_effect = Exception()
+ m_path_exists.return_value = 0
+ dist = util.get_linux_distro()
+ self.assertEqual(('', '', ''), dist)
+
+ @mock.patch('os.path.exists')
+ @mock.patch('platform.dist')
+ def test_get_linux_distro_plat_data(self, m_platform_dist, m_path_exists):
+ m_platform_dist.return_value = ('foo', '1.1', 'aarch64')
+ m_path_exists.return_value = 0
+ dist = util.get_linux_distro()
+ self.assertEqual(('foo', '1.1', 'aarch64'), dist)
+
+ @mock.patch('os.path.exists')
+ @mock.patch('cloudinit.util.load_file')
+ def test_get_linux_distro_user_set(self, m_user_data, m_path_exists):
+ m_user_data.return_value = 'debian'
+ m_path_exists.side_effect = user_set_distro
+ dist = util.get_linux_distro()
+ self.assertEqual(('debian', 'not set', platform.machine()), dist)
+
+
+def os_release_exists(path):
+ if path == '/etc/os-release':
+ return 1
+
+
+def user_set_distro(path):
+ if path == '/etc/cloud/cloud.cfg.d/cloud-init.user.distro':
+ return 1
--- cloudinit/util.py.orig
+++ cloudinit/util.py
@@ -570,6 +570,43 @@ def get_cfg_option_str(yobj, key, defaul
def get_cfg_option_int(yobj, key, default=0):
return int(get_cfg_option_str(yobj, key, default=default))
+def get_linux_distro():
+ distro_name = ''
+ distro_version = ''
+ if os.path.exists('/etc/cloud/cloud.cfg.d/cloud-init.user.distro'):
+ distro_name = load_file(
+ '/etc/cloud/cloud.cfg.d/cloud-init.user.distro')
+ distro_version = 'not set'
+ elif os.path.exists('/etc/os-release'):
+ os_release = load_file('/etc/os-release').split('\n')
+ for entry in os_release:
+ if entry.startswith('ID='):
+ distro_name = entry.split('=')[-1]
+ if '"' in distro_name:
+ distro_name = distro_name.split('"')[1]
+ if entry.startswith('VERSION_ID='):
+ # Lets hope for the best that distros stay consistent ;)
+ distro_version = entry.split('"')[1]
+ else:
+ dist = ('', '', '')
+ try:
+ # Will be removed in 3.7
+ dist = platform.dist() # pylint: disable=W1505
+ except Exception:
+ pass
+ finally:
+ found = None
+ for entry in dist:
+ if entry:
+ found = 1
+ if not found:
+ msg = 'Unable to determine distribution, template expansion '
+ msg += 'may have unexpected results'
+ LOG.warning(msg)
+ return dist
+
+ return (distro_name, distro_version, platform.machine())
+
def system_info():
info = {
@@ -578,19 +615,19 @@ def system_info():
'release': platform.release(),
'python': platform.python_version(),
'uname': platform.uname(),
- 'dist': platform.dist(), # pylint: disable=W1505
+ 'dist': get_linux_distro()
}
system = info['system'].lower()
var = 'unknown'
if system == "linux":
linux_dist = info['dist'][0].lower()
- if linux_dist in ('centos', 'fedora', 'debian'):
+ if linux_dist in ('centos', 'debian', 'fedora', 'rhel', 'suse'):
var = linux_dist
elif linux_dist in ('ubuntu', 'linuxmint', 'mint'):
var = 'ubuntu'
elif linux_dist == 'redhat':
var = 'rhel'
- elif linux_dist == 'suse':
+ elif linux_dist in ('opensuse', 'sles'):
var = 'suse'
else:
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
@@ -1,3 +1,4 @@
+
# Copyright (C) 2009 Canonical Ltd.
# Copyright (C) 2012 Yahoo! Inc.
#
@@ -25,7 +26,7 @@ from distutils.errors import DistutilsAr
import subprocess
RENDERED_TMPD_PREFIX = "RENDERED_TEMPD"
-
+VARIANT = None
def is_f(p):
return os.path.isfile(p)
@@ -114,10 +115,20 @@ def render_tmpl(template):
atexit.register(shutil.rmtree, tmpd)
bname = os.path.basename(template).rstrip(tmpl_ext)
fpath = os.path.join(tmpd, bname)
- tiny_p([sys.executable, './tools/render-cloudcfg', template, fpath])
+ if VARIANT:
+ tiny_p([sys.executable, './tools/render-cloudcfg', '--variant',
+ VARIANT, template, fpath])
+ else:
+ tiny_p([sys.executable, './tools/render-cloudcfg', template, fpath])
# return path relative to setup.py
return os.path.join(os.path.basename(tmpd), bname)
+# User can set the variant for template rendering
+if '--distro' in sys.argv:
+ idx = sys.argv.index('--distro')
+ VARIANT = sys.argv[idx+1]
+ del sys.argv[idx+1]
+ sys.argv.remove('--distro')
INITSYS_FILES = {
'sysvinit': [f for f in glob('sysvinit/redhat/*') if is_f(f)],
@@ -227,6 +238,19 @@ if not in_virtualenv():
for k in INITSYS_ROOTS.keys():
INITSYS_ROOTS[k] = "/" + INITSYS_ROOTS[k]
+if VARIANT and sys.argv[1] == 'install':
+ base = ETC
+ config_dir = '/cloud/cloud.cfg.d'
+ if sys.argv.index('--root'):
+ root_idx = sys.argv.index('--root')
+ root_loc = sys.argv[root_idx+1]
+ base = root_loc + '/' + ETC
+ if not os.path.exists(base + config_dir):
+ os.makedirs(base + config_dir)
+ usr_distro = open(base + '/cloud/cloud.cfg.d/cloud-init.user.distro', 'w')
+ usr_distro.write(VARIANT)
+ usr_distro.close()
+
data_files = [
(ETC + '/cloud', [render_tmpl("config/cloud.cfg.tmpl")]),
(ETC + '/cloud/cloud.cfg.d', glob('config/cloud.cfg.d/*')),
@@ -259,7 +283,7 @@ requirements = read_requires()
setuptools.setup(
name='cloud-init',
version=get_version(),
- description='EC2 initialisation magic',
+ description='Cloud instance initialisation magic',
author='Scott Moser',
author_email='scott.moser@canonical.com',
url='http://launchpad.net/cloud-init/',