|
Server : Apache System : Linux server.mata-lashes.com 3.10.0-1160.90.1.el7.x86_64 #1 SMP Thu May 4 15:21:22 UTC 2023 x86_64 User : matalashes ( 1004) PHP Version : 8.1.29 Disable Function : NONE Directory : /usr/src/cloud-init/tests/unittests/config/ |
Upload File : |
# This file is part of cloud-init. See LICENSE file for license information.
from unittest import mock
import pytest
from cloudinit.config.cc_grub_dpkg import fetch_idevs, handle
from cloudinit.config.schema import (
SchemaValidationError,
get_schema,
validate_cloudconfig_schema,
)
from cloudinit.subp import ProcessExecutionError, SubpResult
from tests.unittests.helpers import does_not_raise, skipUnlessJsonSchema
class TestFetchIdevs:
"""Tests cc_grub_dpkg.fetch_idevs()"""
# Note: udevadm info returns devices in a large single line string
@pytest.mark.parametrize(
"grub_output,path_exists,expected_log_call,udevadm_output"
",expected_idevs,is_efi_boot",
[
# Inside a container, grub not installed
(
ProcessExecutionError(reason=FileNotFoundError()),
False,
mock.call("'grub-probe' not found in $PATH"),
"",
"",
False,
),
# Inside a container, grub installed
(
ProcessExecutionError(stderr="failed to get canonical path"),
False,
mock.call("grub-probe 'failed to get canonical path'"),
"",
"",
False,
),
# KVM Instance
(
SubpResult("/dev/vda", ""),
True,
None,
(
"/dev/disk/by-path/pci-0000:00:00.0 ",
"/dev/disk/by-path/virtio-pci-0000:00:00.0 ",
),
"/dev/vda",
False,
),
# Xen Instance
(
SubpResult("/dev/xvda", ""),
True,
None,
"",
"/dev/xvda",
False,
),
# NVMe Hardware Instance
(
SubpResult("/dev/nvme1n1", ""),
True,
None,
(
"/dev/disk/by-id/nvme-Company_hash000 ",
"/dev/disk/by-id/nvme-nvme.000-000-000-000-000 ",
"/dev/disk/by-path/pci-0000:00:00.0-nvme-0 ",
),
"/dev/disk/by-id/nvme-Company_hash000",
False,
),
# SCSI Hardware Instance
(
SubpResult("/dev/sda", ""),
True,
None,
(
"/dev/disk/by-id/company-user-1 ",
"/dev/disk/by-id/scsi-0Company_user-1 ",
"/dev/disk/by-path/pci-0000:00:00.0-scsi-0:0:0:0 ",
),
"/dev/disk/by-id/company-user-1",
False,
),
# UEFI Hardware Instance
(
SubpResult("/dev/sda2", ""),
True,
None,
(
"/dev/disk/by-id/scsi-3500a075116e6875a "
"/dev/disk/by-id/scsi-SATA_Crucial_CT525MX3_171816E6875A "
"/dev/disk/by-id/scsi-0ATA_Crucial_CT525MX3_171816E6875A "
"/dev/disk/by-path/pci-0000:00:17.0-ata-1 "
"/dev/disk/by-id/wwn-0x500a075116e6875a "
"/dev/disk/by-id/ata-Crucial_CT525MX300SSD1_171816E6875A"
),
"/dev/disk/by-id/ata-Crucial_CT525MX300SSD1_171816E6875A-"
"part1",
True,
),
],
)
@mock.patch("cloudinit.config.cc_grub_dpkg.is_efi_booted")
@mock.patch("cloudinit.config.cc_grub_dpkg.util.logexc")
@mock.patch("cloudinit.config.cc_grub_dpkg.os.path.exists")
@mock.patch("cloudinit.config.cc_grub_dpkg.subp.subp")
@mock.patch("cloudinit.config.cc_grub_dpkg.LOG")
def test_fetch_idevs(
self,
m_log,
m_subp,
m_exists,
m_logexc,
m_efi_booted,
grub_output,
path_exists,
expected_log_call,
udevadm_output,
expected_idevs,
is_efi_boot,
):
"""Tests outputs from grub-probe and udevadm info against grub_dpkg"""
m_subp.side_effect = [
grub_output,
SubpResult("".join(udevadm_output), ""),
]
m_exists.return_value = path_exists
m_efi_booted.return_value = is_efi_boot
idevs = fetch_idevs()
if is_efi_boot:
assert expected_idevs.startswith(idevs) is True
else:
assert idevs == expected_idevs
if expected_log_call is not None:
assert expected_log_call in m_log.debug.call_args_list
class TestHandle:
"""Tests cc_grub_dpkg.handle()"""
@pytest.mark.parametrize(
"cfg_idevs,cfg_idevs_empty,fetch_idevs_output,"
"expected_log_output,is_uefi",
[
(
# No configuration
None,
None,
"/dev/disk/by-id/nvme-Company_hash000",
(
"Setting grub debconf-set-selections with '%s'",
"grub-pc grub-pc/install_devices string "
"/dev/disk/by-id/nvme-Company_hash000\n"
"grub-pc grub-pc/install_devices_empty boolean false\n",
),
False,
),
(
# idevs set, idevs_empty unset
"/dev/sda",
None,
"/dev/sda",
(
"Setting grub debconf-set-selections with '%s'",
"grub-pc grub-pc/install_devices string /dev/sda\n"
"grub-pc grub-pc/install_devices_empty boolean false\n",
),
False,
),
(
# idevs unset, idevs_empty set
None,
"true",
"/dev/xvda",
(
"Setting grub debconf-set-selections with '%s'",
"grub-pc grub-pc/install_devices string /dev/xvda\n"
"grub-pc grub-pc/install_devices_empty boolean true\n",
),
False,
),
(
# idevs set, idevs_empty set
"/dev/vda",
False,
"/dev/disk/by-id/company-user-1",
(
"Setting grub debconf-set-selections with '%s'",
"grub-pc grub-pc/install_devices string /dev/vda\n"
"grub-pc grub-pc/install_devices_empty boolean false\n",
),
False,
),
(
# idevs set, idevs_empty set
# Respect what the user defines, even if its logically wrong
"/dev/nvme0n1",
True,
"",
(
"Setting grub debconf-set-selections with '%s'",
"grub-pc grub-pc/install_devices string /dev/nvme0n1\n"
"grub-pc grub-pc/install_devices_empty boolean true\n",
),
False,
),
(
# uefi active, idevs set
"/dev/sda1",
False,
"/dev/sda1",
(
"Setting grub debconf-set-selections with '%s'",
"grub-pc grub-efi/install_devices string /dev/sda1\n",
),
True,
),
],
)
@mock.patch("cloudinit.config.cc_grub_dpkg.fetch_idevs")
@mock.patch("cloudinit.config.cc_grub_dpkg.util.logexc")
@mock.patch("cloudinit.config.cc_grub_dpkg.subp.subp")
@mock.patch("cloudinit.config.cc_grub_dpkg.is_efi_booted")
@mock.patch("cloudinit.config.cc_grub_dpkg.LOG")
def test_handle(
self,
m_log,
m_is_efi_booted,
m_subp,
m_logexc,
m_fetch_idevs,
cfg_idevs,
cfg_idevs_empty,
fetch_idevs_output,
expected_log_output,
is_uefi,
):
"""Test setting of correct debconf database entries"""
m_is_efi_booted.return_value = is_uefi
m_fetch_idevs.return_value = fetch_idevs_output
cfg = {"grub_dpkg": {}}
if cfg_idevs is not None:
cfg["grub_dpkg"]["grub-pc/install_devices"] = cfg_idevs
if cfg_idevs_empty is not None:
cfg["grub_dpkg"]["grub-pc/install_devices_empty"] = cfg_idevs_empty
handle(mock.Mock(), cfg, mock.Mock(), mock.Mock())
print(m_log.debug.call_args_list)
m_log.debug.assert_called_with(*expected_log_output)
class TestGrubDpkgSchema:
@pytest.mark.parametrize(
"config, expectation, has_errors",
(
(
{"grub_dpkg": {"grub-pc/install_devices_empty": False}},
does_not_raise(),
None,
),
(
{"grub_dpkg": {"grub-pc/install_devices_empty": "off"}},
pytest.raises(
SchemaValidationError,
match=(
"Cloud config schema deprecations: "
"grub_dpkg.grub-pc/install_devices_empty: "
"Changed in version 22.3. Use a boolean value "
"instead."
),
),
False,
),
(
{"grub_dpkg": {"enabled": "yes"}},
pytest.raises(
SchemaValidationError,
match="'yes' is not of type 'boolean'",
),
True,
),
(
{"grub_dpkg": {"grub-pc/install_devices": ["/dev/sda"]}},
pytest.raises(
SchemaValidationError,
match=r"\['/dev/sda'\] is not of type 'string'",
),
True,
),
(
{"grub-dpkg": {"grub-pc/install_devices_empty": False}},
pytest.raises(
SchemaValidationError,
match=(
"Cloud config schema deprecations: grub-dpkg: An alias"
" for ``grub_dpkg`` Deprecated in version 22.2. Use "
"``grub_dpkg`` instead."
),
),
False,
),
),
)
@skipUnlessJsonSchema()
def test_schema_validation(self, config, expectation, has_errors):
"""Assert expected schema validation and error messages."""
schema = get_schema()
with expectation as exc_info:
validate_cloudconfig_schema(config, schema, strict=True)
if has_errors is not None:
assert has_errors == exc_info.value.has_errors()