Skip to content

Commit

Permalink
Add Amazon EC2 detection for virtual grains (bsc#1195624)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Victor Zhestkov authored Sep 1, 2022
1 parent 7803275 commit 77e90c4
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 0 deletions.
1 change: 1 addition & 0 deletions changelog/62539.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Implementation of Amazon EC2 instance detection and setting `virtual_subtype` grain accordingly including the product if possible to identify.
18 changes: 18 additions & 0 deletions salt/grains/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
Expand Down
4 changes: 4 additions & 0 deletions salt/modules/cmdmod.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -933,6 +934,7 @@ def _run_quiet(
success_retcodes=success_retcodes,
success_stdout=success_stdout,
success_stderr=success_stderr,
ignore_retcode=ignore_retcode,
)["stdout"]


Expand All @@ -955,6 +957,7 @@ def _run_all_quiet(
success_retcodes=None,
success_stdout=None,
success_stderr=None,
ignore_retcode=None,
):

"""
Expand Down Expand Up @@ -987,6 +990,7 @@ def _run_all_quiet(
success_retcodes=success_retcodes,
success_stdout=success_stdout,
success_stderr=success_stderr,
ignore_retcode=ignore_retcode,
)


Expand Down
117 changes: 117 additions & 0 deletions tests/pytests/unit/grains/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 77e90c4

Please sign in to comment.