From d4b8c141f2c330bc09d8c960131c3151c501cd80 Mon Sep 17 00:00:00 2001 From: Abhijeet Kasurde Date: Thu, 16 May 2024 11:57:00 -0700 Subject: [PATCH] FreeBSD: add tests for fact gathering Signed-off-by: Abhijeet Kasurde --- .../module_utils/facts/hardware/freebsd.py | 108 ++++---- .../devices => fixtures/devices_freebsd.txt} | 0 .../facts/hardware/fixtures/dmesg_freebsd.txt | 9 + .../expected_devices_freebsd.txt} | 0 .../facts/hardware/fixtures/fstab_freebsd.txt | 4 + .../hardware/fixtures/swapinfo_freebsd.txt | 2 + .../hardware/fixtures/sysctl_freebsd.txt | 255 ++++++++++++++++++ .../hardware/freebsd/test_get_device_facts.py | 23 -- .../facts/hardware/test_freebsd_facts.py | 201 ++++++++++++++ 9 files changed, 525 insertions(+), 77 deletions(-) rename test/units/module_utils/facts/hardware/{freebsd/fixtures/devices => fixtures/devices_freebsd.txt} (100%) create mode 100644 test/units/module_utils/facts/hardware/fixtures/dmesg_freebsd.txt rename test/units/module_utils/facts/hardware/{freebsd/fixtures/expected_devices => fixtures/expected_devices_freebsd.txt} (100%) create mode 100644 test/units/module_utils/facts/hardware/fixtures/fstab_freebsd.txt create mode 100644 test/units/module_utils/facts/hardware/fixtures/swapinfo_freebsd.txt create mode 100644 test/units/module_utils/facts/hardware/fixtures/sysctl_freebsd.txt delete mode 100644 test/units/module_utils/facts/hardware/freebsd/test_get_device_facts.py create mode 100644 test/units/module_utils/facts/hardware/test_freebsd_facts.py diff --git a/lib/ansible/module_utils/facts/hardware/freebsd.py b/lib/ansible/module_utils/facts/hardware/freebsd.py index c7f6c6c48b6..fabb45348d2 100644 --- a/lib/ansible/module_utils/facts/hardware/freebsd.py +++ b/lib/ansible/module_utils/facts/hardware/freebsd.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 @@ -22,6 +10,7 @@ import struct import time from ansible.module_utils.facts.hardware.base import Hardware, HardwareCollector +from ansible.module_utils.facts.sysctl import get_sysctl from ansible.module_utils.facts.timeout import TimeoutError, timeout from ansible.module_utils.facts.utils import get_file_content, get_mount_size @@ -45,6 +34,7 @@ class FreeBSDHardware(Hardware): def populate(self, collected_facts=None): hardware_facts = {} + self.sysctl = get_sysctl(self.module, ['hw', 'vm.stats']) cpu_facts = self.get_cpu_facts() memory_facts = self.get_memory_facts() uptime_facts = self.get_uptime_facts() @@ -69,15 +59,18 @@ class FreeBSDHardware(Hardware): def get_cpu_facts(self): cpu_facts = {} cpu_facts['processor'] = [] - sysctl = self.module.get_bin_path('sysctl') - if sysctl: - rc, out, err = self.module.run_command("%s -n hw.ncpu" % sysctl, check_rc=False) - cpu_facts['processor_count'] = out.strip() + cpu_facts['processor_count'] = self.sysctl.get('hw.ncpu') or '' dmesg_boot = get_file_content(FreeBSDHardware.DMESG_BOOT) if not dmesg_boot: + dmesg_cmd = self.module.get_bin_path( + "dmesg", + warning="falling back to sysctl for processor_count, default to [] for processor" + ) + if dmesg_cmd is None: + return cpu_facts try: - rc, dmesg_boot, err = self.module.run_command(self.module.get_bin_path("dmesg"), check_rc=False) + rc, dmesg_boot, err = self.module.run_command(dmesg_cmd, check_rc=False) except Exception: dmesg_boot = '' @@ -93,45 +86,48 @@ class FreeBSDHardware(Hardware): def get_memory_facts(self): memory_facts = {} - sysctl = self.module.get_bin_path('sysctl') - if sysctl: - rc, out, err = self.module.run_command("%s vm.stats" % sysctl, check_rc=False) - for line in out.splitlines(): - data = line.split() - if 'vm.stats.vm.v_page_size' in line: - pagesize = int(data[1]) - if 'vm.stats.vm.v_page_count' in line: - pagecount = int(data[1]) - if 'vm.stats.vm.v_free_count' in line: - freecount = int(data[1]) - memory_facts['memtotal_mb'] = pagesize * pagecount // 1024 // 1024 - memory_facts['memfree_mb'] = pagesize * freecount // 1024 // 1024 - - swapinfo = self.module.get_bin_path('swapinfo') - if swapinfo: - # Get swapinfo. swapinfo output looks like: - # Device 1M-blocks Used Avail Capacity - # /dev/ada0p3 314368 0 314368 0% - # - rc, out, err = self.module.run_command("%s -k" % swapinfo) - lines = out.splitlines() - if len(lines[-1]) == 0: - lines.pop() - data = lines[-1].split() - if data[0] != 'Device': - memory_facts['swaptotal_mb'] = int(data[1]) // 1024 - memory_facts['swapfree_mb'] = int(data[3]) // 1024 + pagesize = pagecount = freecount = None + if 'vm.stats.vm.v_page_size' in self.sysctl: + pagesize = int(self.sysctl['vm.stats.vm.v_page_size']) + if 'vm.stats.vm.v_page_count' in self.sysctl: + pagecount = int(self.sysctl['vm.stats.vm.v_page_count']) + if 'vm.stats.vm.v_free_count' in self.sysctl: + freecount = int(self.sysctl['vm.stats.vm.v_free_count']) + if pagesize is not None: + if pagecount is not None: + memory_facts['memtotal_mb'] = pagesize * pagecount // 1024 // 1024 + if freecount is not None: + memory_facts['memfree_mb'] = pagesize * freecount // 1024 // 1024 + + swapinfo_cmd = self.module.get_bin_path('swapinfo', warning="skipping swap facts") + if swapinfo_cmd is None: + return memory_facts + + # Get swapinfo. swapinfo output looks like: + # Device 1M-blocks Used Avail Capacity + # /dev/ada0p3 314368 0 314368 0% + # + rc, out, err = self.module.run_command("%s -k" % swapinfo_cmd) + lines = out.splitlines() + if len(lines[-1]) == 0: + lines.pop() + data = lines[-1].split() + if data[0] != 'Device': + memory_facts['swaptotal_mb'] = int(data[1]) // 1024 + memory_facts['swapfree_mb'] = int(data[3]) // 1024 return memory_facts def get_uptime_facts(self): # On FreeBSD, the default format is annoying to parse. # Use -b to get the raw value and decode it. - sysctl_cmd = self.module.get_bin_path('sysctl') + sysctl_cmd = self.module.get_bin_path('sysctl', warning="skipping uptime fact") + if not sysctl_cmd: + return {} cmd = [sysctl_cmd, '-b', 'kern.boottime'] # We need to get raw bytes, not UTF-8. - rc, out, err = self.module.run_command(cmd, encoding=None) + rc, out, _ = self.module.run_command(cmd, encoding=None) # kern.boottime returns seconds and microseconds as two 64-bits # fields, but we are only interested in the first field. @@ -158,10 +154,12 @@ class FreeBSDHardware(Hardware): continue fields = re.sub(r'\s+', ' ', line).split() mount_statvfs_info = get_mount_size(fields[1]) - mount_info = {'mount': fields[1], - 'device': fields[0], - 'fstype': fields[2], - 'options': fields[3]} + mount_info = { + 'mount': fields[1], + 'device': fields[0], + 'fstype': fields[2], + 'options': fields[3] + } mount_info.update(mount_statvfs_info) mount_facts['mounts'].append(mount_info) @@ -231,7 +229,9 @@ class FreeBSDHardware(Hardware): dmi_facts = {} # Fall back to using dmidecode, if available - dmi_bin = self.module.get_bin_path('dmidecode') + dmi_bin = self.module.get_bin_path('dmidecode', warning="skipping dmi facts") + if not dmi_bin: + return dmi_facts DMI_DICT = { 'bios_date': 'bios-release-date', 'bios_vendor': 'bios-vendor', diff --git a/test/units/module_utils/facts/hardware/freebsd/fixtures/devices b/test/units/module_utils/facts/hardware/fixtures/devices_freebsd.txt similarity index 100% rename from test/units/module_utils/facts/hardware/freebsd/fixtures/devices rename to test/units/module_utils/facts/hardware/fixtures/devices_freebsd.txt diff --git a/test/units/module_utils/facts/hardware/fixtures/dmesg_freebsd.txt b/test/units/module_utils/facts/hardware/fixtures/dmesg_freebsd.txt new file mode 100644 index 00000000000..283705513ab --- /dev/null +++ b/test/units/module_utils/facts/hardware/fixtures/dmesg_freebsd.txt @@ -0,0 +1,9 @@ +CPU: Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz (2893.05-MHz K8-class CPU) + Origin = "GenuineIntel" Id = 0x206d7 Stepping = 7 + Features=0xbfebfbff + Features2=0x15bee3ff,DTES64,MON,DS_CPL,VMX,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,,DCA,SSE4.1,SSE4.2,x2APIC,POPCNT,,XSAVE,> + AMD Features=0x2c100800 + AMD Features2=0x1 + TSC: P-state invariant + Cores per package: 16 + Logical CPUs per core: 2 \ No newline at end of file diff --git a/test/units/module_utils/facts/hardware/freebsd/fixtures/expected_devices b/test/units/module_utils/facts/hardware/fixtures/expected_devices_freebsd.txt similarity index 100% rename from test/units/module_utils/facts/hardware/freebsd/fixtures/expected_devices rename to test/units/module_utils/facts/hardware/fixtures/expected_devices_freebsd.txt diff --git a/test/units/module_utils/facts/hardware/fixtures/fstab_freebsd.txt b/test/units/module_utils/facts/hardware/fixtures/fstab_freebsd.txt new file mode 100644 index 00000000000..42202051b73 --- /dev/null +++ b/test/units/module_utils/facts/hardware/fixtures/fstab_freebsd.txt @@ -0,0 +1,4 @@ +# Custom /etc/fstab for FreeBSD VM images +/dev/gpt/rootfs / ufs rw 1 1 +/dev/gpt/swapfs none swap sw 0 0 +/dev/gpt/efiesp /boot/efi msdosfs rw 2 2 diff --git a/test/units/module_utils/facts/hardware/fixtures/swapinfo_freebsd.txt b/test/units/module_utils/facts/hardware/fixtures/swapinfo_freebsd.txt new file mode 100644 index 00000000000..0bf9609faf6 --- /dev/null +++ b/test/units/module_utils/facts/hardware/fixtures/swapinfo_freebsd.txt @@ -0,0 +1,2 @@ +Device 1K-blocks Used Avail Capacity +/dev/gpt/swapfs 1048576 0 1048576 0% \ No newline at end of file diff --git a/test/units/module_utils/facts/hardware/fixtures/sysctl_freebsd.txt b/test/units/module_utils/facts/hardware/fixtures/sysctl_freebsd.txt new file mode 100644 index 00000000000..8dfdcc5089c --- /dev/null +++ b/test/units/module_utils/facts/hardware/fixtures/sysctl_freebsd.txt @@ -0,0 +1,255 @@ +hw.machine: arm64 +hw.model: Apple Unknown CPU r0p0 (midr: 610f0000) +hw.ncpu: 4 +hw.byteorder: 1234 +hw.physmem: 4266598400 +hw.usermem: 3843821568 +hw.pagesize: 4096 +hw.machine_arch: aarch64 +hw.realmem: 4294967296 +hw.acpi.cpu.cx_lowest: C1 +hw.acpi.handle_reboot: 0 +hw.acpi.disable_on_reboot: 0 +hw.acpi.verbose: 0 +hw.acpi.s4bios: 0 +hw.acpi.sleep_delay: 1 +hw.acpi.suspend_state: NONE +hw.acpi.standby_state: NONE +hw.acpi.lid_switch_state: NONE +hw.acpi.sleep_button_state: NONE +hw.acpi.power_button_state: NONE +hw.acpi.supported_sleep_state: +hw.imx.last_reset_reason: unknown +hw.imx.last_reset_status: 0 +hw.genet.tx_hdr_min: 56 +hw.genet.rx_batch: 16 +hw.aw_mmc.debug: 0 +hw.busdma.zone0.alignment: 4096 +hw.busdma.zone0.lowaddr: 0xfffffffffffffff +hw.busdma.zone0.total_deferred: 0 +hw.busdma.zone0.total_bounced: 0 +hw.busdma.zone0.active_bpages: 0 +hw.busdma.zone0.reserved_bpages: 0 +hw.busdma.zone0.free_bpages: 434 +hw.busdma.zone0.total_bpages: 434 +hw.busdma.total_bpages: 434 +hw.bus.devctl_queue: 1000 +hw.pagesizes: { 4096, 2097152, 1073741824 } +hw.availpages: 1041650 +hw.intr_epoch_batch: 1000 +hw.intr_storm_threshold: 0 +hw.watchdog.wd_last_u_secs: 0 +hw.watchdog.wd_last_u: 0 +hw.vtnet.lro_mbufq_depth: 0 +hw.vtnet.lro_entry_count: 128 +hw.vtnet.rx_process_limit: 1024 +hw.vtnet.tso_maxlen: 65535 +hw.vtnet.mq_max_pairs: 32 +hw.vtnet.mq_disable: 0 +hw.vtnet.lro_disable: 0 +hw.vtnet.tso_disable: 0 +hw.vtnet.fixup_needs_csum: 0 +hw.vtnet.csum_disable: 0 +hw.usb.wmt.timestamps: 0 +hw.usb.wmt.debug: 0 +hw.usb.usbhid.debug: 0 +hw.usb.usbhid.enable: 0 +hw.usb.uhid.debug: 0 +hw.usb.ukbd.pollrate: 0 +hw.usb.ukbd.no_leds: 0 +hw.usb.ukbd.debug: 0 +hw.usb.ure.debug: 0 +hw.usb.smsc.debug: 0 +hw.usb.smsc.smsc_rx_packet_batching: 1 +hw.usb.muge.debug: 0 +hw.usb.full_ddesc: 0 +hw.usb.no_cs_fail: 0 +hw.usb.proc.debug: 0 +hw.usb.disable_port_power: 0 +hw.usb.disable_enumeration: 0 +hw.usb.power_timeout: 30 +hw.usb.uhub.debug: 0 +hw.usb.ugen.debug: 0 +hw.usb.usb_lang_mask: 255 +hw.usb.usb_lang_id: 9 +hw.usb.template: -1 +hw.usb.dev.debug: 0 +hw.usb.timings.enum_nice_time: 16 +hw.usb.timings.extra_power_up_time: 20 +hw.usb.timings.resume_recovery: 50 +hw.usb.timings.resume_wait: 50 +hw.usb.timings.resume_delay: 250 +hw.usb.timings.set_address_settle: 10 +hw.usb.timings.port_resume_delay: 40 +hw.usb.timings.port_powerup_delay: 300 +hw.usb.timings.port_reset_recovery: 10 +hw.usb.timings.port_root_reset_delay: 200 +hw.usb.timings.port_reset_delay: 50 +hw.usb.debug: 0 +hw.usb.umass.throttle: 0 +hw.usb.umass.debug: 0 +hw.usb.no_shutdown_wait: 0 +hw.usb.no_suspend_wait: 0 +hw.usb.no_boot_wait: 0 +hw.usb.ctrl.debug: 0 +hw.usb.xhci.ctlstep: 0 +hw.usb.xhci.dma32: 0 +hw.usb.xhci.use_polling: 0 +hw.usb.xhci.xhci_port_route: 0 +hw.usb.xhci.debug: 0 +hw.usb.xhci.dcepquirk: 0 +hw.usb.xhci.ctlquirk: 1 +hw.usb.xhci.streams: 0 +hw.usb.uhci.loop: 0 +hw.usb.uhci.debug: 0 +hw.usb.ohci.debug: 0 +hw.usb.ehci.lostintrbug: 0 +hw.usb.ehci.iaadbug: 0 +hw.usb.ehci.no_hs: 0 +hw.usb.ehci.debug: 0 +hw.usb.dwc_otg.debug: 0 +hw.usb.dwc_otg.phy_type: 1 +hw.usb.musbotg.debug: 0 +hw.broken_txfifo: 0 +hw.midi.seq.debug: 0 +hw.midi.instroff: 0 +hw.midi.dumpraw: 0 +hw.midi.debug: 0 +hw.midi.stat.verbose: 0 +hw.snd.maxautovchans: 16 +hw.snd.default_unit: -1 +hw.snd.version: 2009061500/aarch64 +hw.snd.default_auto: -1 +hw.snd.verbose: 0 +hw.snd.vpc_mixer_bypass: 1 +hw.snd.feeder_rate_quality: 1 +hw.snd.feeder_rate_round: 25 +hw.snd.feeder_rate_max: 2016000 +hw.snd.feeder_rate_min: 1 +hw.snd.feeder_rate_polyphase_max: 183040 +hw.snd.feeder_rate_presets: 100:8:0.85 100:36:0.92 100:164:0.97 +hw.snd.feeder_eq_exact_rate: 0 +hw.snd.feeder_eq_presets: PEQ:16000,0.2500,62,0.2500:-9,9,1.0:44100,48000,88200,96000,176400,192000 +hw.snd.basename_clone: 1 +hw.snd.compat_linux_mmap: 0 +hw.snd.syncdelay: -1 +hw.snd.usefrags: 0 +hw.snd.vpc_reset: 0 +hw.snd.vpc_0db: 45 +hw.snd.vpc_autoreset: 1 +hw.snd.timeout: 5 +hw.snd.latency_profile: 1 +hw.snd.latency: 2 +hw.snd.report_soft_matrix: 1 +hw.snd.report_soft_formats: 1 +hw.sdhci.enable_msi: 1 +hw.sdhci.quirk_set: 0 +hw.sdhci.quirk_clear: 0 +hw.sdhci.debug: 0 +hw.pci.default_vgapci_unit: 0 +hw.pci.enable_pcie_ei: 0 +hw.pci.enable_pcie_hp: 1 +hw.pci.clear_pcib: 0 +hw.pci.iov_max_config: 1048576 +hw.pci.enable_mps_tune: 1 +hw.pci.clear_aer_on_attach: 0 +hw.pci.enable_aspm: 1 +hw.pci.enable_ari: 1 +hw.pci.clear_buses: 0 +hw.pci.clear_bars: 0 +hw.pci.usb_early_takeover: 0 +hw.pci.honor_msi_blacklist: 1 +hw.pci.msix_rewrite_table: 0 +hw.pci.enable_msix: 1 +hw.pci.enable_msi: 1 +hw.pci.do_power_suspend: 1 +hw.pci.do_power_resume: 1 +hw.pci.do_power_nodriver: 0 +hw.pci.realloc_bars: 1 +hw.pci.enable_io_modes: 1 +hw.nvme.verbose_cmd_dump: 0 +hw.nvme.use_nvd: 0 +hw.nvd.delete_max: 1073741824 +hw.mmcsd.cache: 1 +hw.mmc.debug: 0 +hw.kbd.keymap_restrict_change: 0 +hw.ix.enable_aim: 0 +hw.ix.enable_rss: 1 +hw.ix.enable_fdir: 0 +hw.ix.unsupported_sfp: 0 +hw.ix.enable_msix: 1 +hw.ix.advertise_speed: 0 +hw.ix.flow_control: 3 +hw.ix.max_interrupt_rate: 31250 +hw.hid.debug: 0 +hw.em.max_interrupt_rate: 8000 +hw.em.eee_setting: 1 +hw.em.sbp: 0 +hw.em.unsupported_tso: 0 +hw.em.smart_pwr_down: 0 +hw.em.rx_abs_int_delay: 66 +hw.em.tx_abs_int_delay: 66 +hw.em.rx_int_delay: 0 +hw.em.tx_int_delay: 66 +hw.em.disable_crc_stripping: 0 +hw.efi.poweroff: 1 +vm.stats.page.queue_nops: 277052 +vm.stats.page.queue_ops: 16993468 +vm.stats.page.pqstate_commit_retries: 85 +vm.stats.object.collapse_waits: 2 +vm.stats.object.bypasses: 12219 +vm.stats.object.collapses: 73995 +vm.stats.vm.v_pdpages: 1074918 +vm.stats.vm.v_tcached: 0 +vm.stats.vm.v_cache_count: 0 +vm.stats.vm.v_user_wire_count: 0 +vm.stats.vm.v_free_severe: 3927 +vm.stats.vm.v_interrupt_free_min: 2 +vm.stats.vm.v_pageout_free_min: 34 +vm.stats.vm.v_laundry_count: 2962 +vm.stats.vm.v_inactive_count: 860261 +vm.stats.vm.v_inactive_target: 32550 +vm.stats.vm.v_active_count: 543 +vm.stats.vm.v_wire_count: 103217 +vm.stats.vm.v_free_count: 68475 +vm.stats.vm.v_free_min: 6466 +vm.stats.vm.v_free_target: 21700 +vm.stats.vm.v_free_reserved: 1388 +vm.stats.vm.v_page_count: 1015745 +vm.stats.vm.v_page_size: 4096 +vm.stats.vm.v_kthreadpages: 0 +vm.stats.vm.v_rforkpages: 968 +vm.stats.vm.v_vforkpages: 230467 +vm.stats.vm.v_forkpages: 797867 +vm.stats.vm.v_kthreads: 16 +vm.stats.vm.v_rforks: 28 +vm.stats.vm.v_vforks: 6560 +vm.stats.vm.v_forks: 19429 +vm.stats.vm.v_tfree: 8473607 +vm.stats.vm.v_pfree: 3886261 +vm.stats.vm.v_dfree: 523786 +vm.stats.vm.v_pdshortfalls: 0 +vm.stats.vm.v_pdwakeups: 55 +vm.stats.vm.v_reactivated: 6543 +vm.stats.vm.v_intrans: 6216 +vm.stats.vm.v_vnodepgsout: 76 +vm.stats.vm.v_vnodepgsin: 36073 +vm.stats.vm.v_vnodeout: 6 +vm.stats.vm.v_vnodein: 5438 +vm.stats.vm.v_swappgsout: 0 +vm.stats.vm.v_swappgsin: 0 +vm.stats.vm.v_swapout: 0 +vm.stats.vm.v_swapin: 0 +vm.stats.vm.v_ozfod: 82 +vm.stats.vm.v_zfod: 2914018 +vm.stats.vm.v_cow_optim: 985 +vm.stats.vm.v_cow_faults: 1380853 +vm.stats.vm.v_io_faults: 4221 +vm.stats.vm.v_vm_faults: 4919073 +vm.stats.sys.v_soft: 4759911 +vm.stats.sys.v_intr: 333592972 +vm.stats.sys.v_syscall: 40627449 +vm.stats.sys.v_trap: 71581 +vm.stats.sys.v_swtch: 38590569 +vm.stats.swap.free_completed: 0 +vm.stats.swap.free_deferred: 0 diff --git a/test/units/module_utils/facts/hardware/freebsd/test_get_device_facts.py b/test/units/module_utils/facts/hardware/freebsd/test_get_device_facts.py deleted file mode 100644 index 08f64c1dffd..00000000000 --- a/test/units/module_utils/facts/hardware/freebsd/test_get_device_facts.py +++ /dev/null @@ -1,23 +0,0 @@ -# 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 json -import os -import pathlib - -from ansible.module_utils.facts.hardware import freebsd - - -def test_get_device_facts(monkeypatch): - fixtures = pathlib.Path(__file__).parent / 'fixtures' - dev_dir = (fixtures / 'devices').read_text().split() - expected_dev_dir = json.load(open(fixtures / 'expected_devices', 'r')) - - monkeypatch.setattr(os.path, 'isdir', lambda x: True) - monkeypatch.setattr(os, 'listdir', lambda x: dev_dir) - - freebsd_hardware = freebsd.FreeBSDHardware(None) - facts = freebsd_hardware.get_device_facts() - assert facts == expected_dev_dir diff --git a/test/units/module_utils/facts/hardware/test_freebsd_facts.py b/test/units/module_utils/facts/hardware/test_freebsd_facts.py new file mode 100644 index 00000000000..fbc615c27c4 --- /dev/null +++ b/test/units/module_utils/facts/hardware/test_freebsd_facts.py @@ -0,0 +1,201 @@ +# 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 pathlib +import json + +import pytest + +from ansible.module_utils.facts.hardware import freebsd +from ansible.module_utils.facts.sysctl import get_sysctl + + +class TestFreeBSDHardwareFacts: + fixtures = pathlib.Path(__file__).parent / "fixtures" + + def _get_mock_sysctl_data(self): + return (self.fixtures / "sysctl_freebsd.txt").read_text() + + def _get_mock_dmesg_data(self): + return (self.fixtures / "dmesg_freebsd.txt").read_text() + + @pytest.fixture() + def mocked_module(self, mocker, request): + request.cls.module = mocker.MagicMock() + yield request.cls.module + + def test_get_dmi_facts(self, mocker, mocked_module): + freebsd_hardware = freebsd.FreeBSDHardware(mocked_module) + mocker.patch.object( + mocked_module, + "get_bin_path", + side_effect=[ + "/usr/local/sbin/dmidecode", + ], + ) + expected_dmi_facts = { + "bios_date": "2024-05-10", + "bios_vendor": "American Megatrends Inc.", + "bios_version": "1.2.3", + "board_asset_tag": "MyAssetTag1", + "board_name": "Motherboard X399", + "board_serial": "1234ABCD-EFGH-5678", + "board_vendor": "Gigabyte Technology Co., Ltd.", + "board_version": "A00", + "chassis_asset_tag": "MyChassisTag", + "chassis_serial": "9876-FEDC-BA09", + "chassis_vendor": "InWin Development Inc.", + "chassis_version": "Not Available", + "form_factor": "8 (Tower)", + "product_name": "ProBook 450 G8", + "product_serial": "CDEFG1234567890A", + "product_uuid": "123e4567-e89b-12d3-a456-426655440000", + "product_version": "Not Available", + "system_vendor": "Hewlett-Packard", + } + side_effect_list = [(0, i, "") for i in expected_dmi_facts.values()] + + mocker.patch.object(mocked_module, "run_command", side_effect=side_effect_list) + + dmi_facts = freebsd_hardware.get_dmi_facts() + assert dmi_facts == expected_dmi_facts + + def test_get_cpu_facts(self, mocker, mocked_module): + mocker.patch.object( + mocked_module, + "get_bin_path", + side_effect=[ + "/sbin/sysctl", + "/sbin/dmesg", + ], + ) + mocker.patch.object( + mocked_module, + "run_command", + side_effect=[ + (0, self._get_mock_sysctl_data(), ""), + (0, self._get_mock_dmesg_data(), ""), + ], + ) + + freebsd_hardware = freebsd.FreeBSDHardware(mocked_module) + freebsd_hardware.sysctl = get_sysctl(mocked_module, ["hw", "vm.stats"]) + + cpu_facts = freebsd_hardware.get_cpu_facts() + expected_cpu_facts = { + "processor": [ + "Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz (2893.05-MHz K8-class CPU)" + ], + "processor_cores": "2", + "processor_count": "4", + } + assert cpu_facts == expected_cpu_facts + + def test_get_memory_facts(self, mocked_module): + mocked_module.get_bin_path.side_effect = [ + "/sbin/sysctl", + "/usr/sbin/swapinfo", + ] + + mocked_swapinfo_k_output = (self.fixtures / "swapinfo_freebsd.txt").read_text() + mocked_module.run_command.side_effect = [ + (0, self._get_mock_sysctl_data(), ""), + (0, mocked_swapinfo_k_output, ""), + ] + freebsd_hardware = freebsd.FreeBSDHardware(mocked_module) + freebsd_hardware.sysctl = get_sysctl(mocked_module, ["hw", "vm.stats"]) + + memory_facts = freebsd_hardware.get_memory_facts() + expected_memory_facts = { + "memtotal_mb": 3967, + "memfree_mb": 267, + "swapfree_mb": 1024, + "swaptotal_mb": 1024, + } + assert memory_facts == expected_memory_facts + + def test_get_uptime_facts(self, mocked_module): + freebsd_hardware = freebsd.FreeBSDHardware(mocked_module) + mocked_module.run_command.return_value = ( + 0, + b"\xc0\xa0\x05f\x00\x00\x00\x00\xac-\x05\x00\x00\x00\x00\x00", + "", + ) + uptime_facts = freebsd_hardware.get_uptime_facts() + assert "uptime_seconds" in uptime_facts + + def _mock_get_statvfs_output(self, mount_point): + mount_info = { + "/": { + "size_total": 494384795648, + "size_available": 331951407104, + "block_size": 1048576, + "block_total": 120699413, + "block_available": 81042824, + "block_used": 39656589, + "inode_total": 3242116715, + "inode_available": 3241712960, + "inode_used": 403755, + } + } + return mount_info.get(mount_point, {}) + + def test_get_mount_facts(self, mocker, mocked_module): + freebsd_hardware = freebsd.FreeBSDHardware(mocked_module) + mocked_fstab_output = (self.fixtures / "fstab_freebsd.txt").read_text() + mocker.patch( + "ansible.module_utils.facts.hardware.freebsd.get_file_content", + return_value=mocked_fstab_output, + ) + mocker.patch( + "ansible.module_utils.facts.hardware.freebsd.get_mount_size", + side_effect=self._mock_get_statvfs_output, + ) + + fstab_facts = freebsd_hardware.get_mount_facts() + expected_fstab_facts = { + "mounts": [ + { + "mount": "/", + "device": "/dev/gpt/rootfs", + "fstype": "ufs", + "options": "rw", + "size_total": 494384795648, + "size_available": 331951407104, + "block_size": 1048576, + "block_total": 120699413, + "block_available": 81042824, + "block_used": 39656589, + "inode_total": 3242116715, + "inode_available": 3241712960, + "inode_used": 403755, + }, + { + "mount": "none", + "device": "/dev/gpt/swapfs", + "fstype": "swap", + "options": "sw", + }, + { + "mount": "/boot/efi", + "device": "/dev/gpt/efiesp", + "fstype": "msdosfs", + "options": "rw", + }, + ] + } + assert fstab_facts == expected_fstab_facts + + def test_get_device_facts(self, mocker): + dev_dir = (self.fixtures / "devices_freebsd.txt").read_text().split() + with open(self.fixtures / "expected_devices_freebsd.txt", "r") as fd: + expected_dev_dir = json.load(fd) + + mocker.patch("os.path.isdir", return_value=True) + mocker.patch("os.listdir", return_value=dev_dir) + + freebsd_hardware = freebsd.FreeBSDHardware(None) + facts = freebsd_hardware.get_device_facts() + assert facts == expected_dev_dir