diff --git a/changelogs/fragments/sunos_virtinfo.yml b/changelogs/fragments/sunos_virtinfo.yml new file mode 100644 index 00000000000..14528099eae --- /dev/null +++ b/changelogs/fragments/sunos_virtinfo.yml @@ -0,0 +1,3 @@ +--- +bugfixes: + - sunos - remove hard coding of virtinfo command in facts gathering code (https://github.com/ansible/ansible/pull/84357). diff --git a/lib/ansible/module_utils/facts/virtual/sunos.py b/lib/ansible/module_utils/facts/virtual/sunos.py index 7a595f701a5..6c6ffb291a1 100644 --- a/lib/ansible/module_utils/facts/virtual/sunos.py +++ b/lib/ansible/module_utils/facts/virtual/sunos.py @@ -1,17 +1,5 @@ -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see . +# Copyright: Contributors to the Ansible project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import annotations @@ -77,7 +65,7 @@ class SunOSVirtual(Virtual): if virtinfo: # The output of virtinfo is different whether we are on a machine with logical # domains ('LDoms') on a T-series or domains ('Domains') on a M-series. Try LDoms first. - rc, out, err = self.module.run_command("/usr/sbin/virtinfo -p") + rc, out, err = self.module.run_command([virtinfo, '-p']) # The output contains multiple lines with different keys like this: # DOMAINROLE|impl=LDoms|control=false|io=false|service=false|root=false # The output may also be not formatted and the returncode is set to 0 regardless of the error condition: diff --git a/test/units/module_utils/facts/virtual/test_sunos.py b/test/units/module_utils/facts/virtual/test_sunos.py new file mode 100644 index 00000000000..f003247ecf5 --- /dev/null +++ b/test/units/module_utils/facts/virtual/test_sunos.py @@ -0,0 +1,191 @@ +# -*- coding: utf-8 -*- + +# Copyright: Contributors to the Ansible project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +from __future__ import annotations + +import pytest + +from ansible.module_utils.facts.virtual.sunos import SunOSVirtual + + +class MockVirtualSysctl(SunOSVirtual): + def __init__(self, module): + self.module = module + + +def mock_get_bin_path(filename): + cmd_bins = { + "zonename": "/usr/bin/zonename", + "virtinfo": "/usr/sbin/virtinfo", + } + return cmd_bins.get(filename, None) + + +def test_get_virtual_facts_global(mocker): + module = mocker.Mock() + module.get_bin_path.side_effect = mock_get_bin_path + module.run_command.return_value = (0, "global", "") + mixin = MockVirtualSysctl(module=module) + guest_facts = mixin.get_virtual_facts() + expected = { + "virtualization_tech_guest": set(), + "virtualization_tech_host": set(["zone"]), + } + + assert guest_facts == expected + + +@pytest.mark.parametrize( + ("guest_tech", "expected_guest"), + [ + pytest.param( + "VMware", + "vmware", + id="VMware", + ), + pytest.param( + "VirtualBox", + "virtualbox", + id="VirtualBox", + ), + ], +) +def test_get_virtual_facts_guest(mocker, guest_tech, expected_guest): + module = mocker.Mock() + module.get_bin_path.side_effect = [ + "/usr/bin/zonename", + "/usr/sbin/modinfo", + "/usr/sbin/virtinfo", + ] + module.run_command.side_effect = [ + (0, "local", ""), + (0, guest_tech, ""), + (0, "", ""), + ] + mixin = MockVirtualSysctl(module=module) + guest_facts = mixin.get_virtual_facts() + expected = { + "virtualization_tech_guest": set([expected_guest, "zone"]), + "virtualization_tech_host": set(), + "virtualization_type": expected_guest, + "virtualization_role": "guest", + "container": "zone", + } + + assert guest_facts == expected + + +@pytest.mark.parametrize( + ("guest_tech", "expected_guest"), + [ + pytest.param( + "VMware", + "vmware", + id="VMware", + ), + pytest.param( + "VirtualBox", + "virtualbox", + id="VirtualBox", + ), + ], +) +def test_get_virtual_facts_ldoms(mocker, guest_tech, expected_guest): + module = mocker.Mock() + module.get_bin_path.side_effect = [ + "/usr/bin/zonename", + "/usr/sbin/modinfo", + "/usr/sbin/virtinfo", + ] + module.run_command.side_effect = [ + (0, "local", ""), + (0, guest_tech, ""), + (0, "DOMAINROLE|impl=LDoms", ""), + ] + mixin = MockVirtualSysctl(module=module) + guest_facts = mixin.get_virtual_facts() + expected = { + "virtualization_tech_guest": set(["ldom", expected_guest, "zone"]), + "virtualization_tech_host": set(), + "virtualization_type": "ldom", + "virtualization_role": "guest", + "container": "zone", + } + + assert guest_facts == expected + + +@pytest.mark.parametrize( + ("guest_tech", "expected_guest"), + [ + pytest.param( + "VMware", + "vmware", + id="VMware", + ), + pytest.param( + "VirtualBox", + "virtualbox", + id="VirtualBox", + ), + pytest.param( + "Parallels", + "parallels", + id="Parallels", + ), + pytest.param( + "HVM domU", + "xen", + id="Xen", + ), + pytest.param( + "KVM", + "kvm", + id="KVM", + ), + ], +) +def test_get_virtual_facts_smbios(mocker, guest_tech, expected_guest): + module = mocker.Mock() + module.get_bin_path.side_effect = [ + "/usr/bin/zonename", + None, + None, + "/usr/sbin/smbios", + ] + module.run_command.side_effect = [ + (0, "local", ""), + (0, guest_tech, ""), + ] + mixin = MockVirtualSysctl(module=module) + guest_facts = mixin.get_virtual_facts() + expected = { + "virtualization_tech_guest": set([expected_guest, "zone"]), + "virtualization_tech_host": set(), + "virtualization_type": expected_guest, + "virtualization_role": "guest", + "container": "zone", + } + + assert guest_facts == expected + + +def test_get_virtual_facts_openvz(mocker): + mocker.patch("os.path.exists", return_value=True) + module = mocker.Mock() + module.get_bin_path.side_effect = [ + None, # zonename + "/usr/sbin/virtinfo", + ] + module.run_command.return_value = (0, "", "") + mixin = MockVirtualSysctl(module=module) + guest_facts = mixin.get_virtual_facts() + expected = { + "virtualization_role": "guest", + "virtualization_tech_guest": set(["virtuozzo"]), + "virtualization_tech_host": set(), + "virtualization_type": "virtuozzo", + } + + assert guest_facts == expected