Skip to content

Commit

Permalink
Fix virtual grains for VMs running on Nutanix AHV (bsc#1234022)
Browse files Browse the repository at this point in the history
  • Loading branch information
meaksh committed Jan 22, 2025
1 parent 70fb4dc commit 8f1380c
Show file tree
Hide file tree
Showing 2 changed files with 284 additions and 0 deletions.
282 changes: 282 additions & 0 deletions salt/fix-virtual-grains-for-vms-running-on-nutanix-ahv-bs.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
From 609a9fb9c0a66fa57b02f03267bbaa00bd624f20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Wed, 22 Jan 2025 13:01:39 +0000
Subject: [PATCH] Fix virtual grains for VMs running on Nutanix AHV
(bsc#1234022) (#697)

* Fix virtual grains for Nutanix AHV instances

* Add changelog
---
changelog/67180.fixed.md | 1 +
salt/grains/core.py | 14 ++
tests/pytests/unit/grains/test_core.py | 184 +++++++++++++++++++++++++
3 files changed, 199 insertions(+)
create mode 100644 changelog/67180.fixed.md

diff --git a/changelog/67180.fixed.md b/changelog/67180.fixed.md
new file mode 100644
index 0000000000..bcdc0e9360
--- /dev/null
+++ b/changelog/67180.fixed.md
@@ -0,0 +1 @@
+Fix virtual grains for VMs running on Nutanix AHV
diff --git a/salt/grains/core.py b/salt/grains/core.py
index 98bbd3868e..84d5b179dd 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -768,6 +768,9 @@ def _windows_virtual(osdata):
# Manufacturer: Parallels Software International Inc.
elif "Parallels" in manufacturer:
grains["virtual"] = "Parallels"
+ elif "Nutanix" in manufacturer and "AHV" in product_name:
+ grains["virtual"] = "kvm"
+ grains["virtual_subtype"] = "Nutanix AHV"
# Apache CloudStack
elif "CloudStack KVM Hypervisor" in productname:
grains["virtual"] = "kvm"
@@ -927,6 +930,10 @@ def _virtual(osdata):
elif "parallels" in line:
grains["virtual"] = "Parallels"
break
+ elif "nutanix" in line:
+ grains["virtual"] = "kvm"
+ grains["virtual_subtype"] = "Nutanix AHV"
+ break
elif "hyperv" in line:
grains["virtual"] = "HyperV"
break
@@ -978,6 +985,9 @@ def _virtual(osdata):
grains["virtual"] = "Parallels"
elif "Manufacturer: Google" in output:
grains["virtual"] = "kvm"
+ elif "Manufacturer: Nutanix" in output and "Product Name: AHV" in output:
+ grains["virtual"] = "kvm"
+ grains["virtual_subtype"] = "Nutanix AHV"
# Proxmox KVM
elif "Vendor: SeaBIOS" in output:
grains["virtual"] = "kvm"
@@ -1234,6 +1244,7 @@ def _virtual(osdata):
grains["virtual"] = "virtual"

# Try to detect if the instance is running on Amazon EC2
+ # or Nutanix AHV
if grains["virtual"] in ("qemu", "kvm", "xen", "amazon"):
dmidecode = salt.utils.path.which("dmidecode")
if dmidecode:
@@ -1253,6 +1264,9 @@ def _virtual(osdata):
elif re.match(r".*Version: [^\r\n]+\.amazon.*", output, flags=re.DOTALL):
grains["virtual_subtype"] = "Amazon EC2"

+ elif "Manufacturer: Nutanix" in output and "Product Name: AHV" in output:
+ grains["virtual_subtype"] = "Nutanix AHV"
+
for command in failed_commands:
log.info(
"Although '%s' was found in path, the current user "
diff --git a/tests/pytests/unit/grains/test_core.py b/tests/pytests/unit/grains/test_core.py
index b64b8c4bf8..3d2beaa2c9 100644
--- a/tests/pytests/unit/grains/test_core.py
+++ b/tests/pytests/unit/grains/test_core.py
@@ -2770,6 +2770,10 @@ def test_virtual_has_virtual_grain():
{"kernel": "Windows", "manufacturer": "Parallels Software"},
{"virtual": "Parallels"},
),
+ (
+ {"kernel": "Windows", "manufacturer": "Nutanix", "product_name": "AHV"},
+ {"virtual": "kvm", "virtual_subtype": "Nutanix AHV"},
+ ),
],
)
def test__windows_virtual(osdata, expected):
@@ -3453,6 +3457,186 @@ def test_virtual_linux_proc_files_with_non_utf8_chars():
assert virt_grains == {"virtual": "physical"}


+@pytest.mark.skip_unless_on_linux
+def test_virtual_nutanix_virt_what():
+ 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",
+ ]
+ )
+ cmd_run_all_mock = MagicMock(
+ side_effect=[
+ # Check with virt-what
+ {"retcode": 0, "stderr": "", "stdout": "nutanix_ahv"},
+ {
+ "retcode": 0,
+ "stderr": "",
+ "stdout": "\n".join(
+ [
+ "dmidecode 3.4",
+ "Getting SMBIOS data from sysfs.",
+ "SMBIOS 2.8 present.",
+ "",
+ "Handle 0x0001, DMI type 1, 27 bytes",
+ "System Information",
+ " Manufacturer: Nutanix",
+ " Product Name: AHV",
+ " 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",
+ "",
+ "Handle 0x2000, DMI type 32, 11 bytes",
+ "System Boot Information",
+ " Status: No errors detected",
+ ]
+ ),
+ },
+ ]
+ )
+
+ 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"] == "kvm"
+ assert virtual_grains["virtual_subtype"] == "Nutanix AHV"
+
+
+@pytest.mark.skip_unless_on_linux
+def test_virtual_nutanix_dmidecode():
+ osdata = {}
+
+ (
+ osdata["kernel"],
+ osdata["nodename"],
+ osdata["kernelrelease"],
+ osdata["kernelversion"],
+ osdata["cpuarch"],
+ _,
+ ) = platform.uname()
+
+ which_mock = MagicMock(
+ side_effect=[
+ # Check with virt-what
+ None,
+ None,
+ None,
+ "/usr/sbin/dmidecode",
+ None,
+ "/usr/sbin/dmidecode",
+ ]
+ )
+ cmd_run_all_mock = MagicMock(
+ side_effect=[
+ {
+ "retcode": 0,
+ "stderr": "",
+ "stdout": "\n".join(
+ [
+ "dmidecode 3.4",
+ "Getting SMBIOS data from sysfs.",
+ "SMBIOS 2.8 present.",
+ "",
+ "Handle 0x0001, DMI type 1, 27 bytes",
+ "System Information",
+ " Manufacturer: Nutanix",
+ " Product Name: AHV",
+ " 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",
+ "",
+ "Handle 0x2000, DMI type 32, 11 bytes",
+ "System Boot Information",
+ " Status: No errors detected",
+ ]
+ ),
+ },
+ {
+ "retcode": 0,
+ "stderr": "",
+ "stdout": "\n".join(
+ [
+ "dmidecode 3.4",
+ "Getting SMBIOS data from sysfs.",
+ "SMBIOS 2.8 present.",
+ "",
+ "Handle 0x0001, DMI type 1, 27 bytes",
+ "System Information",
+ " Manufacturer: Nutanix",
+ " Product Name: AHV",
+ " 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",
+ "",
+ "Handle 0x2000, DMI type 32, 11 bytes",
+ "System Boot Information",
+ " Status: No errors detected",
+ ]
+ ),
+ },
+ ]
+ )
+
+ def _mock_is_file(filename):
+ if filename in (
+ "/proc/1/cgroup",
+ "/proc/cpuinfo",
+ "/sys/devices/virtual/dmi/id/product_name",
+ "/proc/xen/xsd_kva",
+ "/proc/xen/capabilities",
+ ):
+ return False
+ return True
+
+ 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,
+ },
+ ), patch("os.path.isfile", _mock_is_file), patch(
+ "os.path.isdir", return_value=False
+ ):
+ virtual_grains = core._virtual(osdata.copy())
+
+ assert virtual_grains["virtual"] == "kvm"
+ assert virtual_grains["virtual_subtype"] == "Nutanix AHV"
+
+
@pytest.mark.skip_unless_on_linux
def test_virtual_set_virtual_ec2():
osdata = {}
--
2.47.0

2 changes: 2 additions & 0 deletions salt/salt.spec
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,8 @@ Patch148: revert-setting-selinux-context-for-minion-service-bs.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/66899
# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/698
Patch149: fix-issues-that-break-salt-in-python-3.12-and-3.13-6.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/67181
Patch150: fix-virtual-grains-for-vms-running-on-nutanix-ahv-bs.patch

### IMPORTANT: The line below is used as a snippet marker. Do not touch it.
### SALT PATCHES LIST END
Expand Down

0 comments on commit 8f1380c

Please sign in to comment.