File add-amazon-ec2-detection-for-virtual-grains-bsc-1195.patch of Package salt.26143

From 77e90c4925a4268c5975cf1ce0bb0e4c457618c1 Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <Victor.Zhestkov@suse.com>
Date: Thu, 1 Sep 2022 14:46:24 +0300
Subject: [PATCH] Add Amazon EC2 detection for virtual grains
 (bsc#1195624)

* Add ignore_retcode to quiet run functions

* Implement Amazon EC2 detection for virtual grains

* Add test for virtual grain detection of Amazon EC2

* Also detect the product of Amazon EC2 instance

* Add changelog entry
---
 changelog/62539.added                  |   1 +
 salt/grains/core.py                    |  18 ++++
 salt/modules/cmdmod.py                 |   4 +
 tests/pytests/unit/grains/test_core.py | 117 +++++++++++++++++++++++++
 4 files changed, 140 insertions(+)
 create mode 100644 changelog/62539.added

diff --git a/changelog/62539.added b/changelog/62539.added
new file mode 100644
index 0000000000..5f402d61c2
--- /dev/null
+++ b/changelog/62539.added
@@ -0,0 +1 @@
+Implementation of Amazon EC2 instance detection and setting `virtual_subtype` grain accordingly including the product if possible to identify.
diff --git a/salt/grains/core.py b/salt/grains/core.py
index c5d996d1bb..9530a43fc5 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -1173,6 +1173,24 @@ def _virtual(osdata):
     if grains.get("virtual_subtype") and grains["virtual"] == "physical":
         grains["virtual"] = "virtual"
 
+    # Try to detect if the instance is running on Amazon EC2
+    if grains["virtual"] in ("qemu", "kvm", "xen"):
+        dmidecode = salt.utils.path.which("dmidecode")
+        if dmidecode:
+            ret = __salt__["cmd.run_all"](
+                [dmidecode, "-t", "system"], ignore_retcode=True
+            )
+            output = ret["stdout"]
+            if "Manufacturer: Amazon EC2" in output:
+                grains["virtual_subtype"] = "Amazon EC2"
+                product = re.match(
+                    r".*Product Name: ([^\r\n]*).*", output, flags=re.DOTALL
+                )
+                if product:
+                    grains["virtual_subtype"] = "Amazon EC2 ({})".format(product[1])
+            elif re.match(r".*Version: [^\r\n]+\.amazon.*", output, flags=re.DOTALL):
+                grains["virtual_subtype"] = "Amazon EC2"
+
     for command in failed_commands:
         log.info(
             "Although '%s' was found in path, the current user "
diff --git a/salt/modules/cmdmod.py b/salt/modules/cmdmod.py
index 61b328b13b..cd42e2cda0 100644
--- a/salt/modules/cmdmod.py
+++ b/salt/modules/cmdmod.py
@@ -907,6 +907,7 @@ def _run_quiet(
     success_retcodes=None,
     success_stdout=None,
     success_stderr=None,
+    ignore_retcode=None,
 ):
     """
     Helper for running commands quietly for minion startup
@@ -933,6 +934,7 @@ def _run_quiet(
         success_retcodes=success_retcodes,
         success_stdout=success_stdout,
         success_stderr=success_stderr,
+        ignore_retcode=ignore_retcode,
     )["stdout"]
 
 
@@ -955,6 +957,7 @@ def _run_all_quiet(
     success_retcodes=None,
     success_stdout=None,
     success_stderr=None,
+    ignore_retcode=None,
 ):
 
     """
@@ -987,6 +990,7 @@ def _run_all_quiet(
         success_retcodes=success_retcodes,
         success_stdout=success_stdout,
         success_stderr=success_stderr,
+        ignore_retcode=ignore_retcode,
     )
 
 
diff --git a/tests/pytests/unit/grains/test_core.py b/tests/pytests/unit/grains/test_core.py
index bc3947fa1b..84dd97d62f 100644
--- a/tests/pytests/unit/grains/test_core.py
+++ b/tests/pytests/unit/grains/test_core.py
@@ -2720,3 +2720,120 @@ def test_get_server_id():
 
     with patch.dict(core.__opts__, {"id": "otherid"}):
         assert core.get_server_id() != expected
+
+
+@pytest.mark.skip_unless_on_linux
+def test_virtual_set_virtual_ec2():
+    osdata = {}
+
+    (
+        osdata["kernel"],
+        osdata["nodename"],
+        osdata["kernelrelease"],
+        osdata["kernelversion"],
+        osdata["cpuarch"],
+        _,
+    ) = platform.uname()
+
+    which_mock = MagicMock(
+        side_effect=[
+            # Check with virt-what
+            "/usr/sbin/virt-what",
+            "/usr/sbin/virt-what",
+            None,
+            "/usr/sbin/dmidecode",
+            # Check with systemd-detect-virt
+            None,
+            "/usr/bin/systemd-detect-virt",
+            None,
+            "/usr/sbin/dmidecode",
+            # Check with systemd-detect-virt when no dmidecode available
+            None,
+            "/usr/bin/systemd-detect-virt",
+            None,
+            None,
+        ]
+    )
+    cmd_run_all_mock = MagicMock(
+        side_effect=[
+            # Check with virt-what
+            {"retcode": 0, "stderr": "", "stdout": "xen"},
+            {
+                "retcode": 0,
+                "stderr": "",
+                "stdout": "\n".join(
+                    [
+                        "dmidecode 3.2",
+                        "Getting SMBIOS data from sysfs.",
+                        "SMBIOS 2.7 present.",
+                        "",
+                        "Handle 0x0100, DMI type 1, 27 bytes",
+                        "System Information",
+                        "	Manufacturer: Xen",
+                        "	Product Name: HVM domU",
+                        "	Version: 4.11.amazon",
+                        "	Serial Number: 12345678-abcd-4321-dcba-0123456789ab",
+                        "	UUID: 01234567-dcba-1234-abcd-abcdef012345",
+                        "	Wake-up Type: Power Switch",
+                        "	SKU Number: Not Specified",
+                        "	Family: Not Specified",
+                        "",
+                        "Handle 0x2000, DMI type 32, 11 bytes",
+                        "System Boot Information",
+                        "	Status: No errors detected",
+                    ]
+                ),
+            },
+            # Check with systemd-detect-virt
+            {"retcode": 0, "stderr": "", "stdout": "kvm"},
+            {
+                "retcode": 0,
+                "stderr": "",
+                "stdout": "\n".join(
+                    [
+                        "dmidecode 3.2",
+                        "Getting SMBIOS data from sysfs.",
+                        "SMBIOS 2.7 present.",
+                        "",
+                        "Handle 0x0001, DMI type 1, 27 bytes",
+                        "System Information",
+                        "	Manufacturer: Amazon EC2",
+                        "	Product Name: m5.large",
+                        "	Version: Not Specified",
+                        "	Serial Number: 01234567-dcba-1234-abcd-abcdef012345",
+                        "	UUID: 12345678-abcd-4321-dcba-0123456789ab",
+                        "	Wake-up Type: Power Switch",
+                        "	SKU Number: Not Specified",
+                        "	Family: Not Specified",
+                    ]
+                ),
+            },
+            # Check with systemd-detect-virt when no dmidecode available
+            {"retcode": 0, "stderr": "", "stdout": "kvm"},
+        ]
+    )
+
+    with patch("salt.utils.path.which", which_mock), patch.dict(
+        core.__salt__,
+        {
+            "cmd.run": salt.modules.cmdmod.run,
+            "cmd.run_all": cmd_run_all_mock,
+            "cmd.retcode": salt.modules.cmdmod.retcode,
+            "smbios.get": salt.modules.smbios.get,
+        },
+    ):
+
+        virtual_grains = core._virtual(osdata.copy())
+
+        assert virtual_grains["virtual"] == "xen"
+        assert virtual_grains["virtual_subtype"] == "Amazon EC2"
+
+        virtual_grains = core._virtual(osdata.copy())
+
+        assert virtual_grains["virtual"] == "kvm"
+        assert virtual_grains["virtual_subtype"] == "Amazon EC2 (m5.large)"
+
+        virtual_grains = core._virtual(osdata.copy())
+
+        assert virtual_grains["virtual"] == "kvm"
+        assert "virtual_subtype" not in virtual_grains
-- 
2.37.2


openSUSE Build Service is sponsored by