You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

190 lines
6.3 KiB

9 months ago
import os
import pytest
from leapp.exceptions import StopActorExecution
from leapp.libraries.common import grub, mdraid
from leapp.libraries.common.testutils import logger_mocked
from leapp.libraries.stdlib import api, CalledProcessError
from leapp.models import DefaultGrub, DefaultGrubInfo
from leapp.utils.deprecation import suppress_deprecation
BOOT_PARTITION = '/dev/vda1'
BOOT_DEVICE = '/dev/vda'
MD_BOOT_DEVICE = '/dev/md0'
MD_BOOT_DEVICES_WITH_GRUB = ['/dev/sda', '/dev/sdb']
VALID_DD = b'GRUB GeomHard DiskRead Error'
INVALID_DD = b'Nothing to see here!'
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
def raise_call_error(args=None):
raise CalledProcessError(
message='A Leapp Command Error occurred.',
command=args,
result={'signal': None, 'exit_code': 1, 'pid': 0, 'stdout': 'fake', 'stderr': 'fake'}
)
class RunMocked(object):
def __init__(self, raise_err=False, boot_on_raid=False):
self.called = 0
self.args = None
self.raise_err = raise_err
self.boot_on_raid = boot_on_raid
def __call__(self, args, encoding=None):
self.called += 1
self.args = args
if self.raise_err:
raise_call_error(args)
if self.args == ['grub2-probe', '--target=device', '/boot']:
stdout = MD_BOOT_DEVICE if self.boot_on_raid else BOOT_PARTITION
elif self.args == ['lsblk', '-spnlo', 'name', BOOT_PARTITION]:
stdout = BOOT_DEVICE
elif self.args[:-1] == ['lsblk', '-spnlo', 'name']:
stdout = self.args[-1][:-1]
return {'stdout': stdout}
def open_mocked(fn, flags):
if fn == BOOT_DEVICE or fn in MD_BOOT_DEVICES_WITH_GRUB:
path = os.path.join(CUR_DIR, 'grub_valid')
else:
path = os.path.join(CUR_DIR, 'grub_invalid')
return open(path, 'r')
def open_invalid(fn, flags):
return open(os.path.join(CUR_DIR, 'grub_invalid'), 'r')
def read_mocked(f, size):
return f.read(size)
def close_mocked(f):
f.close()
@suppress_deprecation(grub.get_grub_device)
def test_get_grub_device_library(monkeypatch):
run_mocked = RunMocked()
monkeypatch.setattr(grub, 'run', run_mocked)
monkeypatch.setattr(os, 'open', open_mocked)
monkeypatch.setattr(os, 'read', read_mocked)
monkeypatch.setattr(os, 'close', close_mocked)
monkeypatch.setattr(api, 'current_logger', logger_mocked())
result = grub.get_grub_device()
assert grub.run.called == 2
assert BOOT_DEVICE == result
assert not api.current_logger.warnmsg
assert 'GRUB is installed on {}'.format(result) in api.current_logger.infomsg
@suppress_deprecation(grub.get_grub_device)
def test_get_grub_device_fail_library(monkeypatch):
# TODO(pstodulk): cover here also case with OSError (covered now in actors,
# so keeping for the future when we have a time)
run_mocked = RunMocked(raise_err=True)
monkeypatch.setattr(grub, 'run', run_mocked)
monkeypatch.setattr(os, 'open', open_mocked)
monkeypatch.setattr(os, 'read', read_mocked)
monkeypatch.setattr(os, 'close', close_mocked)
monkeypatch.setattr(api, 'current_logger', logger_mocked())
with pytest.raises(StopActorExecution):
grub.get_grub_device()
assert grub.run.called == 1
err = 'Could not get name of underlying /boot partition'
assert err in api.current_logger.warnmsg
@suppress_deprecation(grub.get_grub_device)
def test_device_no_grub_library(monkeypatch):
run_mocked = RunMocked()
monkeypatch.setattr(grub, 'run', run_mocked)
monkeypatch.setattr(os, 'open', open_invalid)
monkeypatch.setattr(os, 'read', read_mocked)
monkeypatch.setattr(os, 'close', close_mocked)
monkeypatch.setattr(api, 'current_logger', logger_mocked())
result = grub.get_grub_device()
assert grub.run.called == 2
assert not result
@pytest.mark.parametrize('enabled', [True, False])
def test_is_blscfg_library(monkeypatch, enabled):
bls_cfg_enabled = DefaultGrubInfo(
default_grub_info=[DefaultGrub(name='GRUB_ENABLE_BLSCFG', value='true')]
)
bls_cfg_not_enabled = DefaultGrubInfo(
default_grub_info=[DefaultGrub(name='GRUB_ENABLE_BLSCFG', value='false')]
)
bls_cfg = bls_cfg_enabled if enabled else bls_cfg_not_enabled
result = grub.is_blscfg_enabled_in_defaultgrub(bls_cfg)
if enabled:
assert result
else:
assert not result
def is_mdraid_dev_mocked(dev):
return dev == '/dev/md0'
def test_get_grub_devices_one_device(monkeypatch):
run_mocked = RunMocked()
monkeypatch.setattr(grub, 'run', run_mocked)
monkeypatch.setattr(os, 'open', open_mocked)
monkeypatch.setattr(os, 'read', read_mocked)
monkeypatch.setattr(os, 'close', close_mocked)
monkeypatch.setattr(api, 'current_logger', logger_mocked())
monkeypatch.setattr(mdraid, 'is_mdraid_dev', is_mdraid_dev_mocked)
result = grub.get_grub_devices()
assert grub.run.called == 2
assert [BOOT_DEVICE] == result
assert not api.current_logger.warnmsg
assert 'GRUB is installed on {}'.format(",".join(result)) in api.current_logger.infomsg
@pytest.mark.parametrize(
',component_devs,expected',
[
(['/dev/sda1', '/dev/sdb1'], MD_BOOT_DEVICES_WITH_GRUB),
(['/dev/sda1', '/dev/sdb1', '/dev/sdc1', '/dev/sdd1'], MD_BOOT_DEVICES_WITH_GRUB),
(['/dev/sda2', '/dev/sdc1'], ['/dev/sda']),
(['/dev/sdd3', '/dev/sdb2'], ['/dev/sdb']),
]
)
def test_get_grub_devices_raid_device(monkeypatch, component_devs, expected):
run_mocked = RunMocked(boot_on_raid=True)
monkeypatch.setattr(grub, 'run', run_mocked)
monkeypatch.setattr(os, 'open', open_mocked)
monkeypatch.setattr(os, 'read', read_mocked)
monkeypatch.setattr(os, 'close', close_mocked)
monkeypatch.setattr(api, 'current_logger', logger_mocked())
monkeypatch.setattr(mdraid, 'is_mdraid_dev', is_mdraid_dev_mocked)
def get_component_devices_mocked(raid_dev):
assert raid_dev == MD_BOOT_DEVICE
return component_devs
monkeypatch.setattr(mdraid, 'get_component_devices', get_component_devices_mocked)
result = grub.get_grub_devices()
assert grub.run.called == 1 + len(component_devs) # grub2-probe + Nx lsblk
assert sorted(expected) == result
assert not api.current_logger.warnmsg
assert 'GRUB is installed on {}'.format(",".join(result)) in api.current_logger.infomsg