Merge ~rjschwei/cloud-init:noLnxDistro into cloud-init:master

Proposed by Robert Schweikert
Status: Merged
Approved by: Chad Smith
Approved revision: a0c044737f0557bde3627869dc0436c8ab47d6e6
Merge reported by: Chad Smith
Merged at revision: bbcc5e82e6c8e87ca483150205127cb0436c4cd9
Proposed branch: ~rjschwei/cloud-init:noLnxDistro
Merge into: cloud-init:master
Diff against target: 222 lines (+127/-7)
3 files modified
cloudinit/tests/test_util.py (+77/-1)
cloudinit/util.py (+36/-3)
setup.py (+14/-3)
Reviewer Review Type Date Requested Status
Chad Smith Approve
Server Team CI bot continuous-integration Approve
Review via email: mp+336794@code.launchpad.net

Commit message

util: add get_linux_distro function to replace platform.dist

Allow the user to set the distribution with --distro argument to setup.py.
Fall back is to read /etc/os-release. Final backup is to use
platform.dist() Python function. The platform.dist() function is
deprecated and will be removed in Python 3.7

LP: #1745235

Description of the change

util: add get_linux_distro function to replace platform.dist

Allow the user to set the distribution with --distro argument to setup.py. Fall back is to read /etc/os-release. Final backup is to use platform.dist() Python function. The platform.dist() function is deprecated and will be removed in Python 3.7

LP: #1745235

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:3c1a518f968a0f4caa30dedd4272a60067768ddf
https://jenkins.ubuntu.com/server/job/cloud-init-ci/745/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    SUCCESS: MAAS Compatability Testing
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/745/rebuild

review: Approve (continuous-integration)
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:cffee0de4985ea15e038a439c7f670409614db72
https://jenkins.ubuntu.com/server/job/cloud-init-ci/746/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    SUCCESS: MAAS Compatability Testing
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/746/rebuild

review: Approve (continuous-integration)
Revision history for this message
Chad Smith (chad.smith) :
Revision history for this message
Chad Smith (chad.smith) wrote :

I'm not I don't think we can store any non-dict values in the directory /etc/cloud/cloud.cfg.d/ because all files there are ultimately merged together in a giant system_config dictionary against which all of cloud-init runs.

If we have one offs that you want to store somewhere else, maybe just in /etc/cloud/<filename>, otherwise we risk tracebacks like this in /var/log/cloud-init-output.log

2018-05-14 22:14:46,663 - util.py[WARNING]: Failed loading yaml blob

I'm not really certain why we want to provide a facility for an image to override the distribution detection anyway with a config file on the image. Why not just make sure cloud-init detects properly the system on which it is running? Also, we do have a system_info: distro: <distro-name> config option which affects what underlying distro is selected by cloud-init and it feels like providing this additional mechanism is a bit confusing.

review: Needs Fixing
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

FAILED: Continuous integration, rev:84bcc3cab3222889604ff13367e16ce8144f7feb
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1121/
Executed test runs:
    SUCCESS: Checkout
    FAILED: Unit & Style Tests

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1121/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

FAILED: Continuous integration, rev:923d318ed7622f53f17718e37916db1b9de230bb
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1122/
Executed test runs:
    SUCCESS: Checkout
    FAILED: Unit & Style Tests

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1122/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

FAILED: Continuous integration, rev:9edca71ca9f3bb0bb63c646801ba2c09d18962c4
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1123/
Executed test runs:
    SUCCESS: Checkout
    FAILED: Unit & Style Tests

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1123/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Robert Schweikert (rjschwei) wrote :

> I'm not I don't think we can store any non-dict values in the directory
> /etc/cloud/cloud.cfg.d/ because all files there are ultimately merged together
> in a giant system_config dictionary against which all of cloud-init runs.
>
> If we have one offs that you want to store somewhere else, maybe just in
> /etc/cloud/<filename>, otherwise we risk tracebacks like this in /var/log
> /cloud-init-output.log
>
> 2018-05-14 22:14:46,663 - util.py[WARNING]: Failed loading yaml blob
>
> I'm not really certain why we want to provide a facility for an image to
> override the distribution detection anyway with a config file on the image.
> Why not just make sure cloud-init detects properly the system on which it is
> running? Also, we do have a system_info: distro: <distro-name> config option
> which affects what underlying distro is selected by cloud-init and it feels
> like providing this additional mechanism is a bit confusing.

Scott requested that a method be provided for the user to override the "default" behavior. Thus if we allow the user to override the behavior at build time we have to know if the user did this in case any issues are reported. Therefore the value has to be persisted. If we do not persist the value and we get a question bug report and the config option "system_info: distro: <distro-name>" and the templates do not match the answer can only be "we do not why this happened". But if the file exists then we can say "someone overrode the distro detection mechanism during build"

I moved the file to /etc/cloud

Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:36c6158eb4151d37fecd53ac94b07bde721ee339
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1124/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    SUCCESS: MAAS Compatability Testing
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1124/rebuild

review: Approve (continuous-integration)
Revision history for this message
Chad Smith (chad.smith) wrote :

Robert, thanks for the fixes. I understand wanting to override at distro at build time and ensuring that config templates are properly generated for the target environment. What I'm not to certain about is the overriding dynamic get_linux_distro().

We had a meeting to discuss how we want to approach overriding dyanamic distro detection in your new get_linux_distro function.

I think we want to drop modifying runtime behavior from this branch until we sort a better way to override default behavior of get_linux_distro and correlate that potentially with which cloudinit.distro class if chosen as well.

As you mentioned in IRC, you can reserve the "I told you so" card for when this approach doesn't fly :)

Ultimately, we want to move the ability override distro-detection up to a higher level which has access to the consolidated system_cfg:distro as defined in /etc/cloud/cloud-cfg.d. We've also discussed the possibility of allowing a system_cfg: distro: 'auto' which would enable distro-class auto-detection using your get_linux_distro() versus a static config override from /etc/cloud/cloud.cfg

These approaches are something that will involve a bit more back and forth as far as design, so let's keep this branch simple so we can land it without the inevitable bikeshed when designing the right overridden behavior.

Revision history for this message
Chad Smith (chad.smith) :
Revision history for this message
Robert Schweikert (rjschwei) wrote :

Should be all set now.

Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:a0c044737f0557bde3627869dc0436c8ab47d6e6
https://jenkins.ubuntu.com/server/job/cloud-init-ci/11/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    SUCCESS: MAAS Compatability Testing
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/11/rebuild

review: Approve (continuous-integration)
Revision history for this message
Chad Smith (chad.smith) wrote :

Thank you for this rework Robert. LGTM!

review: Approve
Revision history for this message
Chad Smith (chad.smith) wrote :

Thank you for your merge proposal.

Your branch has been set to 'Work in progress'.
Please set the branch back to 'Needs Review' after resolving the issues below.

Thanks again,
Your friendly neighborhood cloud-init robot.

Please fix the following issues:
------------------------------
Commit message lints:
 - Line #2 has 171 too many characters. Line starts with: "Allow the user to set"...
------------------------------

For more information, see commit message guidelines at
https://cloudinit.readthedocs.io/en/latest/topics/hacking.html#do-these-things-for-each-feature-or-bug

review: Needs Fixing
Revision history for this message
Chad Smith (chad.smith) wrote :

oops sorry robert, automation snafu. fixing and landing

Revision history for this message
Chad Smith (chad.smith) :
review: Approve
Revision history for this message
Chad Smith (chad.smith) wrote :

An upstream commit landed for this bug.

To view that commit see the following URL:
https://git.launchpad.net/cloud-init/commit/?id=bbcc5e82

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/cloudinit/tests/test_util.py b/cloudinit/tests/test_util.py
index 3c05a43..17853fc 100644
--- a/cloudinit/tests/test_util.py
+++ b/cloudinit/tests/test_util.py
@@ -3,11 +3,12 @@
3"""Tests for cloudinit.util"""3"""Tests for cloudinit.util"""
44
5import logging5import logging
6from textwrap import dedent6import platform
77
8import cloudinit.util as util8import cloudinit.util as util
99
10from cloudinit.tests.helpers import CiTestCase, mock10from cloudinit.tests.helpers import CiTestCase, mock
11from textwrap import dedent
1112
12LOG = logging.getLogger(__name__)13LOG = logging.getLogger(__name__)
1314
@@ -16,6 +17,29 @@ MOUNT_INFO = [
16 '153 68 254:0 / /home rw,relatime shared:101 - xfs /dev/sda2 rw,attr2'17 '153 68 254:0 / /home rw,relatime shared:101 - xfs /dev/sda2 rw,attr2'
17]18]
1819
20OS_RELEASE_SLES = dedent("""\
21 NAME="SLES"\n
22 VERSION="12-SP3"\n
23 VERSION_ID="12.3"\n
24 PRETTY_NAME="SUSE Linux Enterprise Server 12 SP3"\n
25 ID="sles"\nANSI_COLOR="0;32"\n
26 CPE_NAME="cpe:/o:suse:sles:12:sp3"\n
27""")
28
29OS_RELEASE_UBUNTU = dedent("""\
30 NAME="Ubuntu"\n
31 VERSION="16.04.3 LTS (Xenial Xerus)"\n
32 ID=ubuntu\n
33 ID_LIKE=debian\n
34 PRETTY_NAME="Ubuntu 16.04.3 LTS"\n
35 VERSION_ID="16.04"\n
36 HOME_URL="http://www.ubuntu.com/"\n
37 SUPPORT_URL="http://help.ubuntu.com/"\n
38 BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"\n
39 VERSION_CODENAME=xenial\n
40 UBUNTU_CODENAME=xenial\n
41""")
42
1943
20class FakeCloud(object):44class FakeCloud(object):
2145
@@ -261,4 +285,56 @@ class TestUdevadmSettle(CiTestCase):
261 self.assertRaises(util.ProcessExecutionError, util.udevadm_settle)285 self.assertRaises(util.ProcessExecutionError, util.udevadm_settle)
262286
263287
288@mock.patch('os.path.exists')
289class TestGetLinuxDistro(CiTestCase):
290
291 @classmethod
292 def os_release_exists(self, path):
293 """Side effect function"""
294 if path == '/etc/os-release':
295 return 1
296
297 @mock.patch('cloudinit.util.load_file')
298 def test_get_linux_distro_quoted_name(self, m_os_release, m_path_exists):
299 """Verify we get the correct name if the os-release file has
300 the distro name in quotes"""
301 m_os_release.return_value = OS_RELEASE_SLES
302 m_path_exists.side_effect = TestGetLinuxDistro.os_release_exists
303 dist = util.get_linux_distro()
304 self.assertEqual(('sles', '12.3', platform.machine()), dist)
305
306 @mock.patch('cloudinit.util.load_file')
307 def test_get_linux_distro_bare_name(self, m_os_release, m_path_exists):
308 """Verify we get the correct name if the os-release file does not
309 have the distro name in quotes"""
310 m_os_release.return_value = OS_RELEASE_UBUNTU
311 m_path_exists.side_effect = TestGetLinuxDistro.os_release_exists
312 dist = util.get_linux_distro()
313 self.assertEqual(('ubuntu', '16.04', platform.machine()), dist)
314
315 @mock.patch('platform.dist')
316 def test_get_linux_distro_no_data(self, m_platform_dist, m_path_exists):
317 """Verify we get no information if os-release does not exist"""
318 m_platform_dist.return_value = ('', '', '')
319 m_path_exists.return_value = 0
320 dist = util.get_linux_distro()
321 self.assertEqual(('', '', ''), dist)
322
323 @mock.patch('platform.dist')
324 def test_get_linux_distro_no_impl(self, m_platform_dist, m_path_exists):
325 """Verify we get an empty tuple when no information exists and
326 Exceptions are not propagated"""
327 m_platform_dist.side_effect = Exception()
328 m_path_exists.return_value = 0
329 dist = util.get_linux_distro()
330 self.assertEqual(('', '', ''), dist)
331
332 @mock.patch('platform.dist')
333 def test_get_linux_distro_plat_data(self, m_platform_dist, m_path_exists):
334 """Verify we get the correct platform information"""
335 m_platform_dist.return_value = ('foo', '1.1', 'aarch64')
336 m_path_exists.return_value = 0
337 dist = util.get_linux_distro()
338 self.assertEqual(('foo', '1.1', 'aarch64'), dist)
339
264# vi: ts=4 expandtab340# vi: ts=4 expandtab
diff --git a/cloudinit/util.py b/cloudinit/util.py
index edfedc7..e7b5bc7 100644
--- a/cloudinit/util.py
+++ b/cloudinit/util.py
@@ -576,6 +576,39 @@ def get_cfg_option_int(yobj, key, default=0):
576 return int(get_cfg_option_str(yobj, key, default=default))576 return int(get_cfg_option_str(yobj, key, default=default))
577577
578578
579def get_linux_distro():
580 distro_name = ''
581 distro_version = ''
582 if os.path.exists('/etc/os-release'):
583 os_release = load_file('/etc/os-release')
584 for line in os_release.splitlines():
585 if line.strip().startswith('ID='):
586 distro_name = line.split('=')[-1]
587 distro_name = distro_name.replace('"', '')
588 if line.strip().startswith('VERSION_ID='):
589 # Lets hope for the best that distros stay consistent ;)
590 distro_version = line.split('=')[-1]
591 distro_version = distro_version.replace('"', '')
592 else:
593 dist = ('', '', '')
594 try:
595 # Will be removed in 3.7
596 dist = platform.dist() # pylint: disable=W1505
597 except Exception:
598 pass
599 finally:
600 found = None
601 for entry in dist:
602 if entry:
603 found = 1
604 if not found:
605 LOG.warning('Unable to determine distribution, template '
606 'expansion may have unexpected results')
607 return dist
608
609 return (distro_name, distro_version, platform.machine())
610
611
579def system_info():612def system_info():
580 info = {613 info = {
581 'platform': platform.platform(),614 'platform': platform.platform(),
@@ -583,19 +616,19 @@ def system_info():
583 'release': platform.release(),616 'release': platform.release(),
584 'python': platform.python_version(),617 'python': platform.python_version(),
585 'uname': platform.uname(),618 'uname': platform.uname(),
586 'dist': platform.dist(), # pylint: disable=W1505619 'dist': get_linux_distro()
587 }620 }
588 system = info['system'].lower()621 system = info['system'].lower()
589 var = 'unknown'622 var = 'unknown'
590 if system == "linux":623 if system == "linux":
591 linux_dist = info['dist'][0].lower()624 linux_dist = info['dist'][0].lower()
592 if linux_dist in ('centos', 'fedora', 'debian'):625 if linux_dist in ('centos', 'debian', 'fedora', 'rhel', 'suse'):
593 var = linux_dist626 var = linux_dist
594 elif linux_dist in ('ubuntu', 'linuxmint', 'mint'):627 elif linux_dist in ('ubuntu', 'linuxmint', 'mint'):
595 var = 'ubuntu'628 var = 'ubuntu'
596 elif linux_dist == 'redhat':629 elif linux_dist == 'redhat':
597 var = 'rhel'630 var = 'rhel'
598 elif linux_dist == 'suse':631 elif linux_dist in ('opensuse', 'sles'):
599 var = 'suse'632 var = 'suse'
600 else:633 else:
601 var = 'linux'634 var = 'linux'
diff --git a/setup.py b/setup.py
index 85b2337..5ed8eae 100755
--- a/setup.py
+++ b/setup.py
@@ -25,7 +25,7 @@ from distutils.errors import DistutilsArgError
25import subprocess25import subprocess
2626
27RENDERED_TMPD_PREFIX = "RENDERED_TEMPD"27RENDERED_TMPD_PREFIX = "RENDERED_TEMPD"
2828VARIANT = None
2929
30def is_f(p):30def is_f(p):
31 return os.path.isfile(p)31 return os.path.isfile(p)
@@ -114,10 +114,20 @@ def render_tmpl(template):
114 atexit.register(shutil.rmtree, tmpd)114 atexit.register(shutil.rmtree, tmpd)
115 bname = os.path.basename(template).rstrip(tmpl_ext)115 bname = os.path.basename(template).rstrip(tmpl_ext)
116 fpath = os.path.join(tmpd, bname)116 fpath = os.path.join(tmpd, bname)
117 tiny_p([sys.executable, './tools/render-cloudcfg', template, fpath])117 if VARIANT:
118 tiny_p([sys.executable, './tools/render-cloudcfg', '--variant',
119 VARIANT, template, fpath])
120 else:
121 tiny_p([sys.executable, './tools/render-cloudcfg', template, fpath])
118 # return path relative to setup.py122 # return path relative to setup.py
119 return os.path.join(os.path.basename(tmpd), bname)123 return os.path.join(os.path.basename(tmpd), bname)
120124
125# User can set the variant for template rendering
126if '--distro' in sys.argv:
127 idx = sys.argv.index('--distro')
128 VARIANT = sys.argv[idx+1]
129 del sys.argv[idx+1]
130 sys.argv.remove('--distro')
121131
122INITSYS_FILES = {132INITSYS_FILES = {
123 'sysvinit': [f for f in glob('sysvinit/redhat/*') if is_f(f)],133 'sysvinit': [f for f in glob('sysvinit/redhat/*') if is_f(f)],
@@ -260,7 +270,7 @@ requirements = read_requires()
260setuptools.setup(270setuptools.setup(
261 name='cloud-init',271 name='cloud-init',
262 version=get_version(),272 version=get_version(),
263 description='EC2 initialisation magic',273 description='Cloud instance initialisation magic',
264 author='Scott Moser',274 author='Scott Moser',
265 author_email='scott.moser@canonical.com',275 author_email='scott.moser@canonical.com',
266 url='http://launchpad.net/cloud-init/',276 url='http://launchpad.net/cloud-init/',
@@ -277,4 +287,5 @@ setuptools.setup(
277 }287 }
278)288)
279289
290
280# vi: ts=4 expandtab291# vi: ts=4 expandtab

Subscribers

People subscribed via source and target branches