← Back to team overview

cloud-init-dev team mailing list archive

[Merge] ~chad.smith/cloud-init:bug/1780481-fix-get-linux-distro into cloud-init:master

 

Chad Smith has proposed merging ~chad.smith/cloud-init:bug/1780481-fix-get-linux-distro into cloud-init:master.

Commit message:
ubuntu,centos,debian: get_linux_distro to align with platform.dist

A recent commit added get_linux_distro to replace the deprecated python
platform.dist module behavior before it is dropped from python.  It added
behavior that was compliant on OpenSuSE and SLES, by returning
(<distro_name>, <distro_version>, <cpu-arch>).

Fix get_linux_distro to behave more like the specific distribution's
platform.dist on ubuntu, centos and debian, which will return the
distribution release codename as the third element instead of <cpu-arch>.

SLES and OpenSUSE will retain their current behavior.

Examples follow: 
('sles', '15', 'x86_64')
('opensuse', '42.3', 'x86_64')
('debian', '9', 'stretch')
('ubuntu', '16.04', 'xenial')
('centos', '7', 'Core')

LP: #1780481

Requested reviews:
  cloud-init commiters (cloud-init-dev)
Related bugs:
  Bug #1780481 in cloud-init: "ubuntu/centos/debian: get_linux_distro has different behavior than platform.dist"
  https://bugs.launchpad.net/cloud-init/+bug/1780481

For more details, see:
https://code.launchpad.net/~chad.smith/cloud-init/+git/cloud-init/+merge/349081
-- 
Your team cloud-init commiters is requested to review the proposed merge of ~chad.smith/cloud-init:bug/1780481-fix-get-linux-distro into cloud-init:master.
diff --git a/cloudinit/tests/test_util.py b/cloudinit/tests/test_util.py
index 17853fc..484171d 100644
--- a/cloudinit/tests/test_util.py
+++ b/cloudinit/tests/test_util.py
@@ -26,6 +26,48 @@ OS_RELEASE_SLES = dedent("""\
     CPE_NAME="cpe:/o:suse:sles:12:sp3"\n
 """)
 
+OS_RELEASE_OPENSUSE = dedent("""\
+NAME="openSUSE Leap"
+VERSION="42.3"
+ID=opensuse
+ID_LIKE="suse"
+VERSION_ID="42.3"
+PRETTY_NAME="openSUSE Leap 42.3"
+ANSI_COLOR="0;32"
+CPE_NAME="cpe:/o:opensuse:leap:42.3"
+BUG_REPORT_URL="https://bugs.opensuse.org";
+HOME_URL="https://www.opensuse.org/";
+""")
+
+OS_RELEASE_CENTOS = dedent("""\
+    NAME="CentOS Linux"
+    VERSION="7 (Core)"
+    ID="centos"
+    ID_LIKE="rhel fedora"
+    VERSION_ID="7"
+    PRETTY_NAME="CentOS Linux 7 (Core)"
+    ANSI_COLOR="0;31"
+    CPE_NAME="cpe:/o:centos:centos:7"
+    HOME_URL="https://www.centos.org/";
+    BUG_REPORT_URL="https://bugs.centos.org/";
+
+    CENTOS_MANTISBT_PROJECT="CentOS-7"
+    CENTOS_MANTISBT_PROJECT_VERSION="7"
+    REDHAT_SUPPORT_PRODUCT="centos"
+    REDHAT_SUPPORT_PRODUCT_VERSION="7"
+""")
+
+OS_RELEASE_DEBIAN = dedent("""\
+PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
+NAME="Debian GNU/Linux"
+VERSION_ID="9"
+VERSION="9 (stretch)"
+ID=debian
+HOME_URL="https://www.debian.org/";
+SUPPORT_URL="https://www.debian.org/support";
+BUG_REPORT_URL="https://bugs.debian.org/";
+""")
+
 OS_RELEASE_UBUNTU = dedent("""\
     NAME="Ubuntu"\n
     VERSION="16.04.3 LTS (Xenial Xerus)"\n
@@ -310,7 +352,31 @@ class TestGetLinuxDistro(CiTestCase):
         m_os_release.return_value = OS_RELEASE_UBUNTU
         m_path_exists.side_effect = TestGetLinuxDistro.os_release_exists
         dist = util.get_linux_distro()
-        self.assertEqual(('ubuntu', '16.04', platform.machine()), dist)
+        self.assertEqual(('ubuntu', '16.04', 'xenial'), dist)
+
+    @mock.patch('cloudinit.util.load_file')
+    def test_get_linux_centos(self, m_os_release, m_path_exists):
+        """Verify we get the correct name and release name on CentOS."""
+        m_os_release.return_value = OS_RELEASE_CENTOS
+        m_path_exists.side_effect = TestGetLinuxDistro.os_release_exists
+        dist = util.get_linux_distro()
+        self.assertEqual(('centos', '7', 'Core'), dist)
+
+    @mock.patch('cloudinit.util.load_file')
+    def test_get_linux_debian(self, m_os_release, m_path_exists):
+        """Verify we get the correct name and release name on Debian."""
+        m_os_release.return_value = OS_RELEASE_DEBIAN
+        m_path_exists.side_effect = TestGetLinuxDistro.os_release_exists
+        dist = util.get_linux_distro()
+        self.assertEqual(('debian', '9', 'stretch'), dist)
+
+    @mock.patch('cloudinit.util.load_file')
+    def test_get_linux_opensuse(self, m_os_release, m_path_exists):
+        """Verify we get the correct name and machine arch on OpenSUSE."""
+        m_os_release.return_value = OS_RELEASE_OPENSUSE
+        m_path_exists.side_effect = TestGetLinuxDistro.os_release_exists
+        dist = util.get_linux_distro()
+        self.assertEqual(('opensuse', '42.3', platform.machine()), dist)
 
     @mock.patch('platform.dist')
     def test_get_linux_distro_no_data(self, m_platform_dist, m_path_exists):
diff --git a/cloudinit/util.py b/cloudinit/util.py
index 6da9511..788ddec 100644
--- a/cloudinit/util.py
+++ b/cloudinit/util.py
@@ -579,16 +579,28 @@ def get_cfg_option_int(yobj, key, default=0):
 def get_linux_distro():
     distro_name = ''
     distro_version = ''
+    flavor = ''
     if os.path.exists('/etc/os-release'):
         os_release = load_file('/etc/os-release')
         for line in os_release.splitlines():
-            if line.strip().startswith('ID='):
-                distro_name = line.split('=')[-1]
+            if not line.strip():
+                continue
+            key, value = line.strip().split('=', 1)
+            if key == 'ID':
+                distro_name = value
                 distro_name = distro_name.replace('"', '')
-            if line.strip().startswith('VERSION_ID='):
+                if 'sles' in distro_name or 'suse' in distro_name:
+                    flavor = platform.machine()
+            elif key == 'VERSION':
+                match = re.match(r'[^ ]+ \((?P<codename>[^)]+)\)', value)
+                if match:
+                    flavor = match.groupdict()['codename']
+            elif key == 'VERSION_ID':
                 # Lets hope for the best that distros stay consistent ;)
                 distro_version = line.split('=')[-1]
                 distro_version = distro_version.replace('"', '')
+            elif key == 'VERSION_CODENAME':
+                flavor = line.split('=')[-1]
     else:
         dist = ('', '', '')
         try:
@@ -606,7 +618,7 @@ def get_linux_distro():
                             'expansion may have unexpected results')
         return dist
 
-    return (distro_name, distro_version, platform.machine())
+    return (distro_name, distro_version, flavor)
 
 
 def system_info():

Follow ups