Jelajahi Sumber

Refactor osdetect for rhel family OSes

Fabian Fulga 2 bulan lalu
induk
melakukan
8f1c6e1e1b

+ 1 - 2
coriolis/osmorphing/amazon.py

@@ -4,12 +4,11 @@
 from oslo_log import log as logging
 
 from coriolis import exception
-from coriolis.osmorphing.osdetect import amazon as amazon_detect
 from coriolis.osmorphing import redhat
 from coriolis import utils
 
 
-AMAZON_DISTRO_NAME_IDENTIFIER = amazon_detect.AMAZON_DISTRO_NAME
+AMAZON_DISTRO_NAME_IDENTIFIER = "Amazon Linux"
 
 LOG = logging.getLogger(__name__)
 

+ 10 - 5
coriolis/osmorphing/centos.py

@@ -4,13 +4,14 @@
 from oslo_log import log as logging
 
 from coriolis import exception
-from coriolis.osmorphing.osdetect import centos as centos_detect
 from coriolis.osmorphing import redhat
 from coriolis import utils
 
 
-CENTOS_DISTRO_IDENTIFIER = centos_detect.CENTOS_DISTRO_IDENTIFIER
-CENTOS_STREAM_DISTRO_IDENTIFIER = centos_detect.CENTOS_STREAM_DISTRO_IDENTIFIER
+CENTOS_DISTRO_IDENTIFIER = "CentOS"
+CENTOS_STREAM_DISTRO_IDENTIFIER = "CentOS Stream"
+CENTOS_LINUX_DISTRO_IDENTIFIER = "CentOS Linux"
+ALMALINUX_DISTRO_IDENTIFIER = "AlmaLinux"
 
 LOG = logging.getLogger(__name__)
 
@@ -22,11 +23,15 @@ class BaseCentOSMorphingTools(redhat.BaseRedHatMorphingTools):
     @classmethod
     def check_os_supported(cls, detected_os_info):
         supported_oses = [
-            CENTOS_STREAM_DISTRO_IDENTIFIER, CENTOS_DISTRO_IDENTIFIER]
+            CENTOS_STREAM_DISTRO_IDENTIFIER,
+            CENTOS_DISTRO_IDENTIFIER,
+            CENTOS_LINUX_DISTRO_IDENTIFIER,
+            ALMALINUX_DISTRO_IDENTIFIER,
+        ]
         if detected_os_info['distribution_name'] not in supported_oses:
             return False
         return cls._version_supported_util(
-            detected_os_info['release_version'], minimum=6)
+            detected_os_info['release_version'], minimum=7)
 
     def enable_repos(self, repo_names):
         """Enable repositories for CentOS.

+ 6 - 5
coriolis/osmorphing/oracle.py

@@ -4,12 +4,12 @@
 from oslo_log import log as logging
 
 from coriolis import exception
-from coriolis.osmorphing.osdetect import oracle as oracle_detect
 from coriolis.osmorphing import redhat
 from coriolis import utils
 
 
-ORACLE_DISTRO_IDENTIFIER = oracle_detect.ORACLE_DISTRO_IDENTIFIER
+ORACLE_DISTRO_IDENTIFIER = "Oracle Linux"
+ORACLE_LINUX_SERVER_DISTRO_IDENTIFIER = "Oracle Linux Server"
 
 LOG = logging.getLogger(__name__)
 
@@ -18,11 +18,12 @@ class BaseOracleMorphingTools(redhat.BaseRedHatMorphingTools):
 
     @classmethod
     def check_os_supported(cls, detected_os_info):
-        if detected_os_info['distribution_name'] != (
-                ORACLE_DISTRO_IDENTIFIER):
+        if detected_os_info['distribution_name'] not in (
+                ORACLE_DISTRO_IDENTIFIER,
+                ORACLE_LINUX_SERVER_DISTRO_IDENTIFIER):
             return False
         return cls._version_supported_util(
-            detected_os_info['release_version'], minimum=6)
+            detected_os_info['release_version'], minimum=7)
 
     def enable_repos(self, repo_names):
         """Enable repositories for Oracle Linux.

+ 0 - 27
coriolis/osmorphing/osdetect/amazon.py

@@ -1,27 +0,0 @@
-# Copyright 2023 Cloudbase Solutions Srl
-# All Rights Reserved.
-
-from coriolis import constants
-from coriolis.osmorphing.osdetect import base
-
-
-AMAZON_DISTRO_IDENTIFIER = "amzn"
-AMAZON_DISTRO_NAME = "Amazon Linux"
-
-
-class AmazonLinuxOSDetectTools(base.BaseLinuxOSDetectTools):
-
-    def detect_os(self):
-        info = {}
-        os_release = self._get_os_release()
-        osid = os_release.get("ID")
-        osname = os_release.get("NAME")
-        if osid == AMAZON_DISTRO_IDENTIFIER or osname == AMAZON_DISTRO_NAME:
-            version = os_release.get("VERSION")
-            friendly_name = "%s %s" % (AMAZON_DISTRO_NAME, version)
-            info = {
-                "os_type": constants.OS_TYPE_LINUX,
-                "distribution_name": AMAZON_DISTRO_NAME,
-                "release_version": version,
-                "friendly_release_name": friendly_name}
-        return info

+ 37 - 0
coriolis/osmorphing/osdetect/base.py

@@ -5,11 +5,15 @@
 import abc
 import os
 
+from oslo_log import log as logging
 from six import with_metaclass
 
+from coriolis import constants
 from coriolis import exception
 from coriolis import utils
 
+LOG = logging.getLogger(__name__)
+
 # Required OS release fields to be returned as declared in the
 # 'schemas.CORIOLIS_DETECTED_OS_MORPHING_INFO_SCHEMA' schema:
 REQUIRED_DETECTED_OS_FIELDS = [
@@ -98,3 +102,36 @@ class BaseLinuxOSDetectTools(BaseOSDetectTools):
         except exception.MinionMachineCommandTimeout as ex:
             raise exception.OSMorphingSSHOperationTimeout(
                 cmd=cmd, timeout=timeout) from ex
+
+
+class LinuxOSDetectUsingOSRelease(BaseLinuxOSDetectTools):
+    """OS detection based on the standard /etc/os-release file."""
+
+    def detect_os(self):
+        """Detect a Linux distro from /etc/os-release."""
+        os_release = self._get_os_release()
+        if not os_release:
+            LOG.warning(
+                "Could not detect OS from /etc/os-release: os_release dict "
+                "was not provided")
+            return {}
+
+        distribution_name = os_release.get("NAME")
+        if not distribution_name:
+            LOG.warning(
+                "Could not detect OS from /etc/os-release: NAME is missing")
+            return {}
+
+        version = os_release.get("VERSION_ID")
+        if not version:
+            LOG.warning(
+                "Could not detect OS from /etc/os-release: VERSION_ID is "
+                "missing")
+            return {}
+
+        return {
+            "os_type": constants.OS_TYPE_LINUX,
+            "distribution_name": distribution_name,
+            "release_version": version,
+            "friendly_release_name": "%s Version %s" % (
+                distribution_name, version)}

+ 0 - 46
coriolis/osmorphing/osdetect/centos.py

@@ -1,46 +0,0 @@
-# Copyright 2020 Cloudbase Solutions Srl
-# All Rights Reserved.
-
-import re
-
-from coriolis import constants
-from coriolis.osmorphing.osdetect import base
-from oslo_log import log as logging
-
-
-LOG = logging.getLogger(__name__)
-CENTOS_DISTRO_IDENTIFIER = "CentOS"
-CENTOS_STREAM_DISTRO_IDENTIFIER = "CentOS Stream"
-ALMA_IDENTIFIER = "AlmaLinux"
-
-
-class CentOSOSDetectTools(base.BaseLinuxOSDetectTools):
-
-    def detect_os(self):
-        info = {}
-        redhat_release_path = "etc/redhat-release"
-        if self._test_path(redhat_release_path):
-            release_info = self._read_file(
-                redhat_release_path).decode().splitlines()
-            if release_info:
-                m = re.match(r"^(.*) release ([0-9]+(\.[0-9]+)*)( \(.*\))?.*$",
-                             release_info[0].strip())
-                if m:
-                    distro, version, _, _ = m.groups()
-                    if (CENTOS_DISTRO_IDENTIFIER not in distro and
-                            ALMA_IDENTIFIER not in distro):
-                        LOG.debug(
-                            "Distro does not appear to be a CentOS or Alma: "
-                            f"{distro}")
-                        return {}
-
-                    distribution_name = CENTOS_DISTRO_IDENTIFIER
-                    if CENTOS_STREAM_DISTRO_IDENTIFIER in distro:
-                        distribution_name = CENTOS_STREAM_DISTRO_IDENTIFIER
-                    info = {
-                        "os_type": constants.OS_TYPE_LINUX,
-                        "distribution_name": distribution_name,
-                        "release_version": version,
-                        "friendly_release_name": "%s Version %s" % (
-                            distribution_name, version)}
-        return info

+ 2 - 11
coriolis/osmorphing/osdetect/manager.py

@@ -5,15 +5,10 @@ from oslo_log import log as logging
 
 from coriolis import constants
 from coriolis import exception
-from coriolis.osmorphing.osdetect import amazon
 from coriolis.osmorphing.osdetect import base
-from coriolis.osmorphing.osdetect import centos
 from coriolis.osmorphing.osdetect import coreos
 from coriolis.osmorphing.osdetect import debian
 from coriolis.osmorphing.osdetect import openwrt
-from coriolis.osmorphing.osdetect import oracle
-from coriolis.osmorphing.osdetect import redhat
-from coriolis.osmorphing.osdetect import rocky
 from coriolis.osmorphing.osdetect import suse
 from coriolis.osmorphing.osdetect import ubuntu
 from coriolis.osmorphing.osdetect import windows
@@ -22,16 +17,12 @@ LOG = logging.getLogger(__name__)
 
 
 LINUX_OS_DETECTION_TOOLS = [
-    amazon.AmazonLinuxOSDetectTools,
-    centos.CentOSOSDetectTools,
     coreos.CoreOSOSDetectTools,
     debian.DebianOSDetectTools,
     openwrt.OpenWRTOSDetectTools,
-    oracle.OracleOSDetectTools,
-    redhat.RedHatOSDetectTools,
-    rocky.RockyLinuxOSDetectTools,
     suse.SUSEOSDetectTools,
-    ubuntu.UbuntuOSDetectTools
+    ubuntu.UbuntuOSDetectTools,
+    base.LinuxOSDetectUsingOSRelease,
 ]
 
 WINDOWS_OS_DETECTION_TOOLS = [windows.WindowsOSDetectTools]

+ 0 - 32
coriolis/osmorphing/osdetect/oracle.py

@@ -1,32 +0,0 @@
-# Copyright 2020 Cloudbase Solutions Srl
-# All Rights Reserved.
-
-import re
-
-from coriolis import constants
-from coriolis.osmorphing.osdetect import base
-
-
-ORACLE_DISTRO_IDENTIFIER = "Oracle Linux"
-
-
-class OracleOSDetectTools(base.BaseLinuxOSDetectTools):
-
-    def detect_os(self):
-        info = {}
-        oracle_release_path = "etc/oracle-release"
-        if self._test_path(oracle_release_path):
-            release_info = self._read_file(
-                oracle_release_path).decode().splitlines()
-            if release_info:
-                m = re.match(r"^(.*) release ([0-9].*)$",
-                             release_info[0].strip())
-                if m:
-                    distro, version = m.groups()
-                    info = {
-                        "os_type": constants.OS_TYPE_LINUX,
-                        "distribution_name": ORACLE_DISTRO_IDENTIFIER,
-                        "release_version": version,
-                        "friendly_release_name": "%s Version %s" % (
-                            distro, version)}
-        return info

+ 0 - 40
coriolis/osmorphing/osdetect/redhat.py

@@ -1,40 +0,0 @@
-# Copyright 2020 Cloudbase Solutions Srl
-# All Rights Reserved.
-
-import re
-
-from oslo_log import log as logging
-
-from coriolis import constants
-from coriolis.osmorphing.osdetect import base
-
-
-LOG = logging.getLogger(__name__)
-RED_HAT_DISTRO_IDENTIFIER = "Red Hat Enterprise Linux"
-
-
-class RedHatOSDetectTools(base.BaseLinuxOSDetectTools):
-
-    def detect_os(self):
-        info = {}
-        redhat_release_path = "etc/redhat-release"
-        if self._test_path(redhat_release_path):
-            release_info = self._read_file(
-                redhat_release_path).decode().splitlines()
-            if release_info:
-                m = re.match(r"^(.*) release ([0-9].*) \((.*)\).*$",
-                             release_info[0].strip())
-                if m:
-                    distro, version, _ = m.groups()
-                    if RED_HAT_DISTRO_IDENTIFIER not in distro:
-                        LOG.debug(
-                            "Distro does not appear to be a RHEL: %s", distro)
-                        return {}
-
-                    info = {
-                        "os_type": constants.OS_TYPE_LINUX,
-                        "distribution_name": RED_HAT_DISTRO_IDENTIFIER,
-                        "release_version": version,
-                        "friendly_release_name": "%s Version %s" % (
-                            RED_HAT_DISTRO_IDENTIFIER, version)}
-        return info

+ 0 - 40
coriolis/osmorphing/osdetect/rocky.py

@@ -1,40 +0,0 @@
-# Copyright 2023 Cloudbase Solutions Srl
-# All Rights Reserved.
-
-import re
-
-from coriolis import constants
-from coriolis.osmorphing.osdetect import base
-from oslo_log import log as logging
-
-
-LOG = logging.getLogger(__name__)
-ROCKY_LINUX_DISTRO_IDENTIFIER = "Rocky Linux"
-
-
-class RockyLinuxOSDetectTools(base.BaseLinuxOSDetectTools):
-
-    def detect_os(self):
-        info = {}
-        redhat_release_path = "etc/redhat-release"
-        if self._test_path(redhat_release_path):
-            release_info = self._read_file(
-                redhat_release_path).decode().splitlines()
-            if release_info:
-                m = re.match(r"^(.*) release ([0-9]+(\.[0-9]+)*)( \(.*\))?.*$",
-                             release_info[0].strip())
-                if m:
-                    distro, version, _, _ = m.groups()
-                    if ROCKY_LINUX_DISTRO_IDENTIFIER not in distro:
-                        LOG.debug(
-                            "Distro does not appear to be a Rocky Linux: %s",
-                            distro)
-                        return {}
-
-                    info = {
-                        "os_type": constants.OS_TYPE_LINUX,
-                        "distribution_name": ROCKY_LINUX_DISTRO_IDENTIFIER,
-                        "release_version": version,
-                        "friendly_release_name": "%s Version %s" % (
-                            ROCKY_LINUX_DISTRO_IDENTIFIER, version)}
-        return info

+ 3 - 5
coriolis/osmorphing/redhat.py

@@ -9,17 +9,15 @@ from oslo_log import log as logging
 
 from coriolis import exception
 from coriolis.osmorphing import base
-from coriolis.osmorphing.osdetect import centos as centos_detect
-from coriolis.osmorphing.osdetect import redhat as redhat_detect
 from coriolis import utils
 
-RED_HAT_DISTRO_IDENTIFIER = redhat_detect.RED_HAT_DISTRO_IDENTIFIER
+RED_HAT_DISTRO_IDENTIFIER = "Red Hat Enterprise Linux"
 
 LOG = logging.getLogger(__name__)
 
 # NOTE: some constants duplicated for backwards-compatibility:
 RELEASE_RHEL = RED_HAT_DISTRO_IDENTIFIER
-RELEASE_CENTOS = centos_detect.CENTOS_DISTRO_IDENTIFIER
+RELEASE_CENTOS = "CentOS"
 RELEASE_FEDORA = "Fedora"
 
 
@@ -34,7 +32,7 @@ class BaseRedHatMorphingTools(base.BaseLinuxOSMorphingTools):
                 RED_HAT_DISTRO_IDENTIFIER):
             return False
         return cls._version_supported_util(
-            detected_os_info['release_version'], minimum=6)
+            detected_os_info['release_version'], minimum=7)
 
     def __init__(self, conn, os_root_dir, os_root_dev,
                  hypervisor, event_manager, detected_os_info,

+ 1 - 2
coriolis/osmorphing/rocky.py

@@ -5,11 +5,10 @@ from oslo_log import log as logging
 
 from coriolis import exception
 from coriolis.osmorphing import centos
-from coriolis.osmorphing.osdetect import rocky as rocky_osdetect
 from coriolis import utils
 
 
-ROCKY_LINUX_DISTRO_IDENTIFIER = rocky_osdetect.ROCKY_LINUX_DISTRO_IDENTIFIER
+ROCKY_LINUX_DISTRO_IDENTIFIER = "Rocky Linux"
 
 LOG = logging.getLogger(__name__)
 

+ 0 - 38
coriolis/tests/osmorphing/osdetect/test_amazon.py

@@ -1,38 +0,0 @@
-# Copyright 2024 Cloudbase Solutions Srl
-# All Rights Reserved.
-
-
-from unittest import mock
-
-from coriolis.osmorphing.osdetect import amazon
-from coriolis.osmorphing.osdetect import base
-from coriolis.tests import test_base
-
-
-class AmazonLinuxOSDetectToolsTestCase(test_base.CoriolisBaseTestCase):
-    """Test suite for AmazonLinuxOSDetectTools class."""
-
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_get_os_release')
-    def test_detect_os(self, mock_get_os_release):
-        mock_get_os_release.return_value = {
-            "ID": "amzn",
-            "VERSION": mock.sentinel.version,
-            "NAME": "Amazon Linux"
-        }
-
-        expected_info = {
-            "os_type": amazon.constants.OS_TYPE_LINUX,
-            "distribution_name": amazon.AMAZON_DISTRO_NAME,
-            "release_version": mock.sentinel.version,
-            "friendly_release_name": "Amazon Linux %s" % mock.sentinel.version
-        }
-
-        amazon_os_detect_tools = amazon.AmazonLinuxOSDetectTools(
-            mock.sentinel.conn, mock.sentinel.os_root_dir,
-            mock.sentinel.operation_timeout)
-
-        result = amazon_os_detect_tools.detect_os()
-
-        mock_get_os_release.assert_called_once_with()
-
-        self.assertEqual(result, expected_info)

+ 223 - 0
coriolis/tests/osmorphing/osdetect/test_base.py

@@ -1,11 +1,18 @@
 # Copyright 2024 Cloudbase Solutions Srl
 # All Rights Reserved.
 
+import logging
 import os
 from unittest import mock
 
+from coriolis import constants
 from coriolis import exception
+from coriolis.osmorphing import amazon as amazon_morphing
+from coriolis.osmorphing import centos
+from coriolis.osmorphing import oracle
 from coriolis.osmorphing.osdetect import base
+from coriolis.osmorphing import redhat as redhat_morphing
+from coriolis.osmorphing import rocky
 from coriolis.tests import test_base
 
 
@@ -170,3 +177,219 @@ class BaseLinuxOSDetectToolsTestCase(test_base.CoriolisBaseTestCase):
             self.base_os_detect._exec_cmd_chroot,
             mock.sentinel.cmd
         )
+
+
+class LinuxOSDetectUsingOSReleaseTestCase(test_base.CoriolisBaseTestCase):
+    """Test suite for the LinuxOSDetectUsingOSRelease class."""
+
+    def setUp(self):
+        super(LinuxOSDetectUsingOSReleaseTestCase, self).setUp()
+        self.os_detect = base.LinuxOSDetectUsingOSRelease(
+            mock.sentinel.conn, mock.sentinel.os_root_dir,
+            mock.sentinel.operation_timeout)
+
+    @mock.patch.object(base.BaseLinuxOSDetectTools, '_get_os_release')
+    def test_detect_os_empty_release(self, mock_get_os_release):
+        with self.assertLogs(
+                'coriolis.osmorphing.osdetect.base',
+                level=logging.WARNING) as logs:
+            mock_get_os_release.return_value = {}
+            self.assertEqual(self.os_detect.detect_os(), {})
+            mock_get_os_release.return_value = None
+            self.assertEqual(self.os_detect.detect_os(), {})
+        self.assertEqual(len(logs.output), 2)
+
+    @mock.patch.object(base.BaseLinuxOSDetectTools, '_get_os_release')
+    def test_detect_os_missing_name(self, mock_get_os_release):
+        mock_get_os_release.return_value = {"ID": "rocky", "VERSION_ID": "8"}
+        with self.assertLogs(
+                'coriolis.osmorphing.osdetect.base',
+                level=logging.WARNING):
+            self.assertEqual(self.os_detect.detect_os(), {})
+
+    @mock.patch.object(base.BaseLinuxOSDetectTools, '_get_os_release')
+    def test_detect_os_missing_version(self, mock_get_os_release):
+        mock_get_os_release.return_value = {
+            "ID": "rocky", "NAME": "Rocky Linux"}
+        with self.assertLogs(
+                'coriolis.osmorphing.osdetect.base',
+                level=logging.WARNING):
+            self.assertEqual(self.os_detect.detect_os(), {})
+
+    @mock.patch.object(base.BaseLinuxOSDetectTools, '_get_os_release')
+    def test_detect_os_centos_stream(self, mock_get_os_release):
+        mock_get_os_release.return_value = {
+            "ID": "centos",
+            "VERSION_ID": "9",
+            "NAME": "CentOS Stream",
+        }
+        expected = {
+            "os_type": constants.OS_TYPE_LINUX,
+            "distribution_name": "CentOS Stream",
+            "release_version": "9",
+            "friendly_release_name": "CentOS Stream Version 9",
+        }
+        self.assertEqual(self.os_detect.detect_os(), expected)
+
+    @mock.patch.object(base.BaseLinuxOSDetectTools, '_get_os_release')
+    def test_detect_os_amazon(self, mock_get_os_release):
+        mock_get_os_release.return_value = {
+            "ID": "amzn",
+            "VERSION_ID": mock.sentinel.version,
+            "NAME": amazon_morphing.AMAZON_DISTRO_NAME_IDENTIFIER,
+        }
+
+        expected = {
+            "os_type": constants.OS_TYPE_LINUX,
+            "distribution_name": amazon_morphing.AMAZON_DISTRO_NAME_IDENTIFIER,
+            "release_version": mock.sentinel.version,
+            "friendly_release_name": "Amazon Linux Version %s" % (
+                mock.sentinel.version)
+        }
+
+        self.assertEqual(self.os_detect.detect_os(), expected)
+
+    @mock.patch.object(base.BaseLinuxOSDetectTools, '_get_os_release')
+    def test_detect_os_rhel(self, mock_get_os_release):
+        mock_get_os_release.return_value = {
+            "ID": "rhel",
+            "VERSION_ID": "8.4",
+            "NAME": "Red Hat Enterprise Linux",
+        }
+
+        expected = {
+            "os_type": constants.OS_TYPE_LINUX,
+            "distribution_name": redhat_morphing.RED_HAT_DISTRO_IDENTIFIER,
+            "release_version": '8.4',
+            "friendly_release_name": "%s Version %s" % (
+                redhat_morphing.RED_HAT_DISTRO_IDENTIFIER, '8.4')
+        }
+
+        self.assertEqual(self.os_detect.detect_os(), expected)
+
+    @mock.patch.object(base.BaseLinuxOSDetectTools, '_get_os_release')
+    def test_detect_os_centos_linux(self, mock_get_os_release):
+        mock_get_os_release.return_value = {
+            "ID": "centos",
+            "VERSION_ID": "7.9",
+            "NAME": centos.CENTOS_LINUX_DISTRO_IDENTIFIER,
+        }
+
+        expected = {
+            "os_type": constants.OS_TYPE_LINUX,
+            "distribution_name": centos.CENTOS_LINUX_DISTRO_IDENTIFIER,
+            "release_version": '7.9',
+            "friendly_release_name": "%s Version %s" % (
+                centos.CENTOS_LINUX_DISTRO_IDENTIFIER, '7.9'),
+        }
+
+        self.assertEqual(self.os_detect.detect_os(), expected)
+
+    @mock.patch.object(base.BaseLinuxOSDetectTools, '_get_os_release')
+    def test_detect_os_centos_stream_8(self, mock_get_os_release):
+        mock_get_os_release.return_value = {
+            "ID": "centos",
+            "VERSION_ID": "8.3",
+            "NAME": "CentOS Stream",
+        }
+
+        expected = {
+            "os_type": constants.OS_TYPE_LINUX,
+            "distribution_name": centos.CENTOS_STREAM_DISTRO_IDENTIFIER,
+            "release_version": '8.3',
+            "friendly_release_name": "%s Version %s" % (
+                centos.CENTOS_STREAM_DISTRO_IDENTIFIER, '8.3')
+        }
+
+        self.assertEqual(self.os_detect.detect_os(), expected)
+
+    @mock.patch.object(base.BaseLinuxOSDetectTools, '_get_os_release')
+    def test_detect_os_centos_stream_10(self, mock_get_os_release):
+        mock_get_os_release.return_value = {
+            "ID": "centos",
+            "VERSION_ID": "10",
+            "NAME": "CentOS Stream",
+        }
+
+        expected = {
+            "os_type": constants.OS_TYPE_LINUX,
+            "distribution_name": centos.CENTOS_STREAM_DISTRO_IDENTIFIER,
+            "release_version": '10',
+            "friendly_release_name": "%s Version %s" % (
+                centos.CENTOS_STREAM_DISTRO_IDENTIFIER, '10')
+        }
+
+        self.assertEqual(self.os_detect.detect_os(), expected)
+
+    @mock.patch.object(base.BaseLinuxOSDetectTools, '_get_os_release')
+    def test_detect_os_almalinux(self, mock_get_os_release):
+        mock_get_os_release.return_value = {
+            "ID": "almalinux",
+            "VERSION_ID": "9.4",
+            "NAME": centos.ALMALINUX_DISTRO_IDENTIFIER,
+            "ID_LIKE": "rhel centos fedora",
+        }
+
+        expected = {
+            "os_type": constants.OS_TYPE_LINUX,
+            "distribution_name": centos.ALMALINUX_DISTRO_IDENTIFIER,
+            "release_version": '9.4',
+            "friendly_release_name": "%s Version %s" % (
+                centos.ALMALINUX_DISTRO_IDENTIFIER, '9.4'),
+        }
+
+        self.assertEqual(self.os_detect.detect_os(), expected)
+
+    @mock.patch.object(base.BaseLinuxOSDetectTools, '_get_os_release')
+    def test_detect_os_oracle(self, mock_get_os_release):
+        mock_get_os_release.return_value = {
+            "ID": "ol",
+            "VERSION_ID": "8.4",
+            "NAME": oracle.ORACLE_LINUX_SERVER_DISTRO_IDENTIFIER,
+        }
+
+        expected = {
+            "os_type": constants.OS_TYPE_LINUX,
+            "distribution_name": (
+                oracle.ORACLE_LINUX_SERVER_DISTRO_IDENTIFIER),
+            "release_version": '8.4',
+            "friendly_release_name": "%s Version %s" % (
+                oracle.ORACLE_LINUX_SERVER_DISTRO_IDENTIFIER, '8.4')
+        }
+
+        self.assertEqual(self.os_detect.detect_os(), expected)
+
+    @mock.patch.object(base.BaseLinuxOSDetectTools, '_get_os_release')
+    def test_detect_os_rocky(self, mock_get_os_release):
+        mock_get_os_release.return_value = {
+            "ID": "rocky",
+            "VERSION_ID": "8.4",
+            "NAME": "Rocky Linux",
+        }
+
+        expected = {
+            "os_type": constants.OS_TYPE_LINUX,
+            "distribution_name": rocky.ROCKY_LINUX_DISTRO_IDENTIFIER,
+            "release_version": '8.4',
+            "friendly_release_name": "Rocky Linux Version 8.4"
+        }
+
+        self.assertEqual(self.os_detect.detect_os(), expected)
+
+    @mock.patch.object(base.BaseLinuxOSDetectTools, '_get_os_release')
+    def test_detect_os_rocky_10(self, mock_get_os_release):
+        mock_get_os_release.return_value = {
+            "ID": "rocky",
+            "VERSION_ID": "10.1",
+            "NAME": "Rocky Linux",
+            "PRETTY_NAME": "Rocky Linux 10.1 (Red Quartz)",
+        }
+
+        expected = {
+            "os_type": constants.OS_TYPE_LINUX,
+            "distribution_name": rocky.ROCKY_LINUX_DISTRO_IDENTIFIER,
+            "release_version": '10.1',
+            "friendly_release_name": "Rocky Linux Version 10.1"
+        }
+
+        self.assertEqual(self.os_detect.detect_os(), expected)

+ 0 - 94
coriolis/tests/osmorphing/osdetect/test_centos.py

@@ -1,94 +0,0 @@
-# Copyright 2024 Cloudbase Solutions Srl
-# All Rights Reserved.
-
-import logging
-from unittest import mock
-
-from coriolis.osmorphing.osdetect import base
-from coriolis.osmorphing.osdetect import centos
-from coriolis.tests import test_base
-
-
-class CentOSOSDetectToolsTestCase(test_base.CoriolisBaseTestCase):
-    """Test suite for the CentOSOSDetectTools class."""
-
-    def setUp(self):
-        super(CentOSOSDetectToolsTestCase, self).setUp()
-        self.centos_os_detect_tools = centos.CentOSOSDetectTools(
-            mock.sentinel.conn, mock.sentinel.os_root_dir,
-            mock.sentinel.operation_timeout)
-
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_test_path')
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_read_file')
-    def test_detect_os(self, mock_read_file, mock_test_path):
-        mock_test_path.return_value = True
-        mock_read_file.return_value = b"CentOS Linux release 7.9 (Core)"
-
-        expected_info = {
-            "os_type": centos.constants.OS_TYPE_LINUX,
-            "distribution_name": centos.CENTOS_DISTRO_IDENTIFIER,
-            "release_version": '7.9',
-            "friendly_release_name": "%s Version %s" % (
-                centos.CENTOS_DISTRO_IDENTIFIER, '7.9')
-        }
-
-        result = self.centos_os_detect_tools.detect_os()
-
-        mock_test_path.assert_called_once_with("etc/redhat-release")
-        mock_read_file.assert_called_once_with("etc/redhat-release")
-
-        self.assertEqual(result, expected_info)
-
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_test_path')
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_read_file')
-    def test_detect_os_centos_stream(self, mock_read_file, mock_test_path):
-        mock_test_path.return_value = True
-        mock_read_file.return_value = b"CentOS Stream release 8.3"
-
-        expected_info = {
-            "os_type": centos.constants.OS_TYPE_LINUX,
-            "distribution_name": centos.CENTOS_STREAM_DISTRO_IDENTIFIER,
-            "release_version": '8.3',
-            "friendly_release_name": "%s Version %s" % (
-                centos.CENTOS_STREAM_DISTRO_IDENTIFIER, '8.3')
-        }
-
-        result = self.centos_os_detect_tools.detect_os()
-
-        mock_test_path.assert_called_once_with("etc/redhat-release")
-        mock_read_file.assert_called_once_with("etc/redhat-release")
-
-        self.assertEqual(result, expected_info)
-
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_test_path')
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_read_file')
-    def test_detect_os_centos_stream_10(self, mock_read_file, mock_test_path):
-        mock_test_path.return_value = True
-        mock_read_file.return_value = b"CentOS Stream release 10"
-
-        expected_info = {
-            "os_type": centos.constants.OS_TYPE_LINUX,
-            "distribution_name": centos.CENTOS_STREAM_DISTRO_IDENTIFIER,
-            "release_version": '10',
-            "friendly_release_name": "%s Version %s" % (
-                centos.CENTOS_STREAM_DISTRO_IDENTIFIER, '10')
-        }
-
-        result = self.centos_os_detect_tools.detect_os()
-
-        self.assertEqual(result, expected_info)
-
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_test_path')
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_read_file')
-    def test_detect_os_not_centos(self, mock_read_file, mock_test_path):
-        mock_test_path.return_value = True
-        mock_read_file.return_value = b"dummy release 8.3"
-
-        with self.assertLogs('coriolis.osmorphing.osdetect.centos',
-                             level=logging.DEBUG):
-            result = self.centos_os_detect_tools.detect_os()
-
-            self.assertEqual(result, {})
-
-        mock_test_path.assert_called_once_with("etc/redhat-release")
-        mock_read_file.assert_called_once_with("etc/redhat-release")

+ 12 - 44
coriolis/tests/osmorphing/osdetect/test_manager.py

@@ -122,18 +122,10 @@ class ManagerTestCase(test_base.CoriolisBaseTestCase):
                           mock.sentinel.operation_timeout)
 
     @mock.patch.object(manager, '_check_custom_os_detect_tools')
-    @mock.patch.object(manager.rocky.RockyLinuxOSDetectTools, 'detect_os')
-    @mock.patch.object(manager.redhat.RedHatOSDetectTools, 'detect_os')
-    @mock.patch.object(manager.centos.CentOSOSDetectTools, 'detect_os')
-    @mock.patch.object(manager.oracle.OracleOSDetectTools, 'detect_os')
+    @mock.patch.object(base.LinuxOSDetectUsingOSRelease, 'detect_os')
     def test_detect_os_no_detected_info(
-            self, mock_oracle_detect_os, mock_centos_detect_os,
-            mock_redhat_detect_os, mock_rocky_detect_os,
-            mock_check_custom_tools):
-        mock_rocky_detect_os.return_value = None
-        mock_redhat_detect_os.return_value = None
-        mock_centos_detect_os.return_value = None
-        mock_oracle_detect_os.return_value = None
+            self, mock_linux_os_detect, mock_check_custom_tools):
+        mock_linux_os_detect.return_value = None
         mock_os_detect_tool = MockOSDetectToolNoInfo
 
         self.assertRaises(exception.OSDetectToolsNotFound, manager.detect_os,
@@ -143,18 +135,10 @@ class ManagerTestCase(test_base.CoriolisBaseTestCase):
         mock_check_custom_tools.assert_called_once_with([mock_os_detect_tool])
 
     @mock.patch.object(manager, '_check_custom_os_detect_tools')
-    @mock.patch.object(manager.rocky.RockyLinuxOSDetectTools, 'detect_os')
-    @mock.patch.object(manager.redhat.RedHatOSDetectTools, 'detect_os')
-    @mock.patch.object(manager.centos.CentOSOSDetectTools, 'detect_os')
-    @mock.patch.object(manager.oracle.OracleOSDetectTools, 'detect_os')
+    @mock.patch.object(base.LinuxOSDetectUsingOSRelease, 'detect_os')
     def test_detect_os_invalid_detected_info(
-            self, mock_oracle_detect_os, mock_centos_detect_os,
-            mock_redhat_detect_os, mock_rocky_detect_os,
-            mock_check_custom_tools):
-        mock_rocky_detect_os.return_value = None
-        mock_redhat_detect_os.return_value = None
-        mock_centos_detect_os.return_value = None
-        mock_oracle_detect_os.return_value = "invalid_detected_info"
+            self, mock_linux_os_detect, mock_check_custom_tools):
+        mock_linux_os_detect.return_value = "invalid_detected_info"
         mock_os_detect_tool = MockOSDetectToolNoInfo
 
         self.assertRaises(exception.InvalidDetectedOSParams, manager.detect_os,
@@ -164,18 +148,10 @@ class ManagerTestCase(test_base.CoriolisBaseTestCase):
         mock_check_custom_tools.assert_called_once_with([mock_os_detect_tool])
 
     @mock.patch.object(manager, '_check_custom_os_detect_tools')
-    @mock.patch.object(manager.rocky.RockyLinuxOSDetectTools, 'detect_os')
-    @mock.patch.object(manager.redhat.RedHatOSDetectTools, 'detect_os')
-    @mock.patch.object(manager.centos.CentOSOSDetectTools, 'detect_os')
-    @mock.patch.object(manager.oracle.OracleOSDetectTools, 'detect_os')
+    @mock.patch.object(base.LinuxOSDetectUsingOSRelease, 'detect_os')
     def test_detect_os_missing_detected_info_fields(
-            self, mock_oracle_detect_os, mock_centos_detect_os,
-            mock_redhat_detect_os, mock_rocky_detect_os,
-            mock_check_custom_tools):
-        mock_rocky_detect_os.return_value = None
-        mock_redhat_detect_os.return_value = None
-        mock_centos_detect_os.return_value = None
-        mock_oracle_detect_os.return_value = None
+            self, mock_linux_os_detect, mock_check_custom_tools):
+        mock_linux_os_detect.return_value = None
         mock_os_detect_tool = MockOSDetectToolMissingFields
 
         self.assertRaises(exception.InvalidDetectedOSParams, manager.detect_os,
@@ -185,18 +161,10 @@ class ManagerTestCase(test_base.CoriolisBaseTestCase):
         mock_check_custom_tools.assert_called_once_with([mock_os_detect_tool])
 
     @mock.patch.object(manager, '_check_custom_os_detect_tools')
-    @mock.patch.object(manager.rocky.RockyLinuxOSDetectTools, 'detect_os')
-    @mock.patch.object(manager.redhat.RedHatOSDetectTools, 'detect_os')
-    @mock.patch.object(manager.centos.CentOSOSDetectTools, 'detect_os')
-    @mock.patch.object(manager.oracle.OracleOSDetectTools, 'detect_os')
+    @mock.patch.object(base.LinuxOSDetectUsingOSRelease, 'detect_os')
     def test_detect_os_extra_detected_info_fields(
-            self, mock_oracle_detect_os, mock_centos_detect_os,
-            mock_redhat_detect_os, mock_rocky_detect_os,
-            mock_check_custom_tools):
-        mock_rocky_detect_os.return_value = None
-        mock_redhat_detect_os.return_value = None
-        mock_centos_detect_os.return_value = None
-        mock_oracle_detect_os.return_value = None
+            self, mock_linux_os_detect, mock_check_custom_tools):
+        mock_linux_os_detect.return_value = None
         mock_os_detect_tool = MockOSDetectToolExtraFields
 
         self.assertRaises(exception.InvalidDetectedOSParams, manager.detect_os,

+ 0 - 35
coriolis/tests/osmorphing/osdetect/test_oracle.py

@@ -1,35 +0,0 @@
-# Copyright 2024 Cloudbase Solutions Srl
-# All Rights Reserved.
-
-from unittest import mock
-
-from coriolis.osmorphing.osdetect import base
-from coriolis.osmorphing.osdetect import oracle
-from coriolis.tests import test_base
-
-
-class OracleOSDetectToolsTestCase(test_base.CoriolisBaseTestCase):
-    """Test suite for the OracleOSDetectTools class."""
-
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_test_path')
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_read_file')
-    def test_detect_os(self, mock_read_file, mock_test_path):
-        mock_test_path.return_value = True
-        mock_read_file.return_value = b"Oracle Linux release 8.4"
-
-        expected_info = {
-            "os_type": oracle.constants.OS_TYPE_LINUX,
-            "distribution_name": oracle.ORACLE_DISTRO_IDENTIFIER,
-            "release_version": '8.4',
-            "friendly_release_name": "Oracle Linux Version 8.4"
-        }
-
-        oracle_os_detect_tools = oracle.OracleOSDetectTools(
-            mock.sentinel.conn, mock.sentinel.os_root_dir,
-            mock.sentinel.operation_timeout)
-
-        result = oracle_os_detect_tools.detect_os()
-        mock_test_path.assert_called_once_with("etc/oracle-release")
-        mock_read_file.assert_called_once_with("etc/oracle-release")
-
-        self.assertEqual(result, expected_info)

+ 0 - 56
coriolis/tests/osmorphing/osdetect/test_redhat.py

@@ -1,56 +0,0 @@
-# Copyright 2024 Cloudbase Solutions Srl
-# All Rights Reserved.
-
-import logging
-from unittest import mock
-
-from coriolis.osmorphing.osdetect import base
-from coriolis.osmorphing.osdetect import redhat
-from coriolis.tests import test_base
-
-
-class RedHatOSDetectToolsTestCase(test_base.CoriolisBaseTestCase):
-    """Test suite for the RedHatOSDetectTools class."""
-
-    def setUp(self):
-        super(RedHatOSDetectToolsTestCase, self).setUp()
-        self.redhat_os_detect_tools = redhat.RedHatOSDetectTools(
-            mock.sentinel.conn, mock.sentinel.os_root_dir,
-            mock.sentinel.operation_timeout)
-
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_test_path')
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_read_file')
-    def test_detect_os(self, mock_read_file, mock_test_path):
-        mock_test_path.return_value = True
-        mock_read_file.return_value = (
-            b"Red Hat Enterprise Linux release 8.4 (Ootpa)")
-
-        expected_info = {
-            "os_type": redhat.constants.OS_TYPE_LINUX,
-            "distribution_name": redhat.RED_HAT_DISTRO_IDENTIFIER,
-            "release_version": '8.4',
-            "friendly_release_name": "%s Version %s" % (
-                redhat.RED_HAT_DISTRO_IDENTIFIER, '8.4')
-        }
-
-        result = self.redhat_os_detect_tools.detect_os()
-
-        mock_test_path.assert_called_once_with("etc/redhat-release")
-        mock_read_file.assert_called_once_with("etc/redhat-release")
-
-        self.assertEqual(result, expected_info)
-
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_test_path')
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_read_file')
-    def test_detect_os_no_redhat(self, mock_read_file, mock_test_path):
-        mock_test_path.return_value = True
-        mock_read_file.return_value = b"CentOS Linux release 8.4 (Ootpa)"
-
-        with self.assertLogs('coriolis.osmorphing.osdetect.redhat',
-                             level=logging.DEBUG):
-            result = self.redhat_os_detect_tools.detect_os()
-
-            self.assertEqual(result, {})
-
-        mock_test_path.assert_called_once_with("etc/redhat-release")
-        mock_read_file.assert_called_once_with("etc/redhat-release")

+ 0 - 75
coriolis/tests/osmorphing/osdetect/test_rocky.py

@@ -1,75 +0,0 @@
-# Copyright 2024 Cloudbase Solutions Srl
-# All Rights Reserved.
-
-from unittest import mock
-
-from coriolis.osmorphing.osdetect import base
-from coriolis.osmorphing.osdetect import rocky
-from coriolis.tests import test_base
-
-
-class RockyLinuxOSDetectToolsTestCase(test_base.CoriolisBaseTestCase):
-    """Test suite for the RockyLinuxOSDetectTools class."""
-
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_test_path')
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_read_file')
-    def test_detect_os(self, mock_read_file, mock_test_path):
-        mock_test_path.return_value = True
-        mock_read_file.return_value = b"Rocky Linux release 8.4"
-
-        expected_info = {
-            "os_type": rocky.constants.OS_TYPE_LINUX,
-            "distribution_name": rocky.ROCKY_LINUX_DISTRO_IDENTIFIER,
-            "release_version": '8.4',
-            "friendly_release_name": "Rocky Linux Version 8.4"
-        }
-
-        rocky_os_detect_tools = rocky.RockyLinuxOSDetectTools(
-            mock.sentinel.conn, mock.sentinel.os_root_dir,
-            mock.sentinel.operation_timeout)
-
-        result = rocky_os_detect_tools.detect_os()
-        mock_test_path.assert_called_once_with("etc/redhat-release")
-        mock_read_file.assert_called_once_with("etc/redhat-release")
-
-        self.assertEqual(result, expected_info)
-
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_test_path')
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_read_file')
-    def test_detect_os_rocky_10(self, mock_read_file, mock_test_path):
-        mock_test_path.return_value = True
-        mock_read_file.return_value = (
-            b"Rocky Linux release 10.1 (Red Quartz)")
-
-        expected_info = {
-            "os_type": rocky.constants.OS_TYPE_LINUX,
-            "distribution_name": rocky.ROCKY_LINUX_DISTRO_IDENTIFIER,
-            "release_version": '10.1',
-            "friendly_release_name": "Rocky Linux Version 10.1"
-        }
-
-        rocky_os_detect_tools = rocky.RockyLinuxOSDetectTools(
-            mock.sentinel.conn, mock.sentinel.os_root_dir,
-            mock.sentinel.operation_timeout)
-
-        result = rocky_os_detect_tools.detect_os()
-
-        self.assertEqual(result, expected_info)
-
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_test_path')
-    @mock.patch.object(base.BaseLinuxOSDetectTools, '_read_file')
-    def test_detect_os_no_rocky(self, mock_read_file, mock_test_path):
-        mock_test_path.return_value = True
-        mock_read_file.return_value = b"CentOS Linux release 8.4"
-
-        with self.assertLogs('coriolis.osmorphing.osdetect.rocky',
-                             level="DEBUG"):
-            rocky_os_detect_tools = rocky.RockyLinuxOSDetectTools(
-                mock.sentinel.conn, mock.sentinel.os_root_dir,
-                mock.sentinel.operation_timeout)
-            result = rocky_os_detect_tools.detect_os()
-
-            self.assertEqual(result, {})
-
-        mock_test_path.assert_called_once_with("etc/redhat-release")
-        mock_read_file.assert_called_once_with("etc/redhat-release")

+ 1 - 1
coriolis/tests/osmorphing/test_centos.py

@@ -34,7 +34,7 @@ class BaseCentOSMorphingToolsTestCase(test_base.CoriolisBaseTestCase):
     def test_check_os_supported(self):
         detected_os_info = {
             "distribution_name": centos.CENTOS_DISTRO_IDENTIFIER,
-            "release_version": "6"
+            "release_version": "7"
         }
 
         result = centos.BaseCentOSMorphingTools.check_os_supported(

+ 2 - 3
coriolis/tests/osmorphing/test_oracle.py

@@ -9,7 +9,6 @@ import ddt
 from coriolis import exception
 from coriolis.osmorphing import base
 from coriolis.osmorphing import oracle
-from coriolis.osmorphing.osdetect import oracle as oracle_detect
 from coriolis.tests import test_base
 
 
@@ -21,8 +20,8 @@ class BaseOracleMorphingToolsTestCase(test_base.CoriolisBaseTestCase):
         super(BaseOracleMorphingToolsTestCase, self).setUp()
         self.detected_os_info = {
             'os_type': 'linux',
-            'distribution_name': oracle_detect.ORACLE_DISTRO_IDENTIFIER,
-            'release_version': '6',
+            'distribution_name': oracle.ORACLE_DISTRO_IDENTIFIER,
+            'release_version': '7',
             'friendly_release_name': mock.sentinel.friendly_release_name,
         }
         self.enable_repos = ['repo1', 'repo2']

+ 1 - 1
coriolis/tests/osmorphing/test_redhat.py

@@ -21,7 +21,7 @@ class BaseRedHatMorphingToolsTestCase(test_base.CoriolisBaseTestCase):
         self.detected_os_info = {
             'os_type': 'linux',
             'distribution_name': redhat.RED_HAT_DISTRO_IDENTIFIER,
-            'release_version': '6',
+            'release_version': '7',
             'friendly_release_name': mock.sentinel.friendly_release_name,
         }
         self.package_names = ['package1', 'package2']