2015-02-19 13:42:39 +00:00
|
|
|
# Copyright 2015 Red Hat, Inc.
|
|
|
|
# All Rights Reserved.
|
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
|
|
# not use this file except in compliance with the License. You may obtain
|
|
|
|
# a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
# License for the specific language governing permissions and limitations
|
|
|
|
# under the License.
|
|
|
|
|
2015-03-12 09:15:49 +00:00
|
|
|
import os
|
2015-02-19 13:42:39 +00:00
|
|
|
import shutil
|
|
|
|
import tempfile
|
2020-04-06 12:28:30 +02:00
|
|
|
from unittest import mock
|
2015-02-19 13:42:39 +00:00
|
|
|
|
2021-08-27 13:28:41 +02:00
|
|
|
from ironic_lib import disk_utils
|
2019-08-06 13:52:13 +02:00
|
|
|
from ironic_lib import utils as ilib_utils
|
2015-02-19 13:42:39 +00:00
|
|
|
from oslo_concurrency import processutils
|
|
|
|
|
2021-10-27 13:45:10 +02:00
|
|
|
from ironic_python_agent import efi_utils
|
2015-02-19 13:42:39 +00:00
|
|
|
from ironic_python_agent import errors
|
|
|
|
from ironic_python_agent.extensions import image
|
|
|
|
from ironic_python_agent import hardware
|
2021-10-27 13:45:10 +02:00
|
|
|
from ironic_python_agent import partition_utils
|
2022-01-31 11:19:10 +01:00
|
|
|
from ironic_python_agent import raid_utils
|
2017-10-18 11:06:30 -07:00
|
|
|
from ironic_python_agent.tests.unit import base
|
2021-02-12 14:47:16 +01:00
|
|
|
from ironic_python_agent.tests.unit.samples import hardware_samples as hws
|
2015-02-19 13:42:39 +00:00
|
|
|
|
|
|
|
|
2023-04-07 07:32:44 -07:00
|
|
|
EFI_RESULT = ''.encode('utf-16')
|
|
|
|
|
|
|
|
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(hardware, 'dispatch_to_managers', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(ilib_utils, 'execute', autospec=True)
|
2015-02-19 13:42:39 +00:00
|
|
|
@mock.patch.object(tempfile, 'mkdtemp', lambda *_: '/tmp/fake-dir')
|
|
|
|
@mock.patch.object(shutil, 'rmtree', lambda *_: None)
|
2017-10-18 11:06:30 -07:00
|
|
|
class TestImageExtension(base.IronicAgentTest):
|
2015-02-19 13:42:39 +00:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestImageExtension, self).setUp()
|
|
|
|
self.agent_extension = image.ImageExtension()
|
|
|
|
self.fake_dev = '/dev/fake'
|
2015-03-12 09:15:49 +00:00
|
|
|
self.fake_efi_system_part = '/dev/fake1'
|
2015-02-19 13:42:39 +00:00
|
|
|
self.fake_root_part = '/dev/fake2'
|
2018-07-11 13:35:54 +00:00
|
|
|
self.fake_prep_boot_part = '/dev/fake3'
|
2015-02-19 13:42:39 +00:00
|
|
|
self.fake_root_uuid = '11111111-2222-3333-4444-555555555555'
|
2015-03-12 09:15:49 +00:00
|
|
|
self.fake_efi_system_part_uuid = '45AB-2312'
|
2018-07-11 13:35:54 +00:00
|
|
|
self.fake_prep_boot_part_uuid = '76937797-3253-8843-999999999999'
|
2015-02-19 13:42:39 +00:00
|
|
|
self.fake_dir = '/tmp/fake-dir'
|
|
|
|
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(image, '_install_grub2', autospec=True)
|
2021-05-10 12:43:17 +02:00
|
|
|
def test__install_bootloader_bios(self, mock_grub2,
|
2019-12-02 16:56:42 +01:00
|
|
|
mock_execute, mock_dispatch):
|
|
|
|
mock_dispatch.side_effect = [
|
|
|
|
self.fake_dev, hardware.BootInfo(current_boot_mode='bios')
|
|
|
|
]
|
2020-06-08 15:10:05 +02:00
|
|
|
self.agent_extension.install_bootloader(
|
|
|
|
root_uuid=self.fake_root_uuid).join()
|
2019-12-02 16:56:42 +01:00
|
|
|
mock_dispatch.assert_any_call('get_os_install_device')
|
|
|
|
mock_dispatch.assert_any_call('get_boot_info')
|
|
|
|
self.assertEqual(2, mock_dispatch.call_count)
|
2015-03-12 09:15:49 +00:00
|
|
|
mock_grub2.assert_called_once_with(
|
|
|
|
self.fake_dev, root_uuid=self.fake_root_uuid,
|
2019-08-06 13:52:13 +02:00
|
|
|
efi_system_part_uuid=None, prep_boot_part_uuid=None,
|
|
|
|
target_boot_mode='bios'
|
|
|
|
)
|
2015-02-19 13:42:39 +00:00
|
|
|
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(efi_utils, 'manage_uefi', autospec=True)
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(image, '_install_grub2', autospec=True)
|
2019-12-02 16:56:42 +01:00
|
|
|
def test__install_bootloader_uefi(self, mock_grub2, mock_uefi,
|
|
|
|
mock_execute, mock_dispatch):
|
|
|
|
mock_dispatch.side_effect = [
|
|
|
|
self.fake_dev, hardware.BootInfo(current_boot_mode='uefi')
|
|
|
|
]
|
|
|
|
mock_uefi.return_value = False
|
2015-03-12 09:15:49 +00:00
|
|
|
self.agent_extension.install_bootloader(
|
|
|
|
root_uuid=self.fake_root_uuid,
|
2019-08-06 13:52:13 +02:00
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
target_boot_mode='uefi'
|
2020-06-08 15:10:05 +02:00
|
|
|
).join()
|
2019-12-02 16:56:42 +01:00
|
|
|
mock_dispatch.assert_any_call('get_os_install_device')
|
|
|
|
mock_dispatch.assert_any_call('get_boot_info')
|
2020-11-24 08:18:49 -08:00
|
|
|
self.assertEqual(2, mock_dispatch.call_count)
|
|
|
|
mock_grub2.assert_called_once_with(
|
|
|
|
self.fake_dev,
|
|
|
|
root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
prep_boot_part_uuid=None,
|
|
|
|
target_boot_mode='uefi'
|
|
|
|
)
|
|
|
|
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(efi_utils, 'manage_uefi', autospec=True)
|
2020-11-24 08:18:49 -08:00
|
|
|
@mock.patch.object(image, '_install_grub2', autospec=True)
|
|
|
|
def test__install_bootloader_uefi_ignores_manage_failure(
|
|
|
|
self, mock_grub2, mock_uefi,
|
|
|
|
mock_execute, mock_dispatch):
|
|
|
|
self.config(ignore_bootloader_failure=True)
|
|
|
|
mock_uefi.side_effect = OSError('meow')
|
|
|
|
mock_dispatch.side_effect = [
|
|
|
|
self.fake_dev, hardware.BootInfo(current_boot_mode='uefi')
|
|
|
|
]
|
|
|
|
mock_uefi.return_value = False
|
|
|
|
self.agent_extension.install_bootloader(
|
|
|
|
root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
target_boot_mode='uefi'
|
|
|
|
).join()
|
|
|
|
mock_dispatch.assert_any_call('get_os_install_device')
|
|
|
|
mock_dispatch.assert_any_call('get_boot_info')
|
|
|
|
self.assertEqual(2, mock_dispatch.call_count)
|
|
|
|
mock_grub2.assert_called_once_with(
|
|
|
|
self.fake_dev,
|
|
|
|
root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
prep_boot_part_uuid=None,
|
|
|
|
target_boot_mode='uefi'
|
|
|
|
)
|
|
|
|
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(efi_utils, 'manage_uefi', autospec=True)
|
2020-11-24 08:18:49 -08:00
|
|
|
@mock.patch.object(image, '_install_grub2', autospec=True)
|
|
|
|
def test__install_bootloader_uefi_ignores_grub_failure(
|
|
|
|
self, mock_grub2, mock_uefi,
|
|
|
|
mock_execute, mock_dispatch):
|
|
|
|
self.config(ignore_bootloader_failure=True)
|
|
|
|
mock_grub2.side_effect = OSError('meow')
|
|
|
|
mock_dispatch.side_effect = [
|
|
|
|
self.fake_dev, hardware.BootInfo(current_boot_mode='uefi')
|
|
|
|
]
|
|
|
|
mock_uefi.return_value = False
|
|
|
|
self.agent_extension.install_bootloader(
|
|
|
|
root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
target_boot_mode='uefi'
|
|
|
|
).join()
|
|
|
|
mock_dispatch.assert_any_call('get_os_install_device')
|
|
|
|
mock_dispatch.assert_any_call('get_boot_info')
|
|
|
|
self.assertEqual(2, mock_dispatch.call_count)
|
|
|
|
mock_grub2.assert_called_once_with(
|
|
|
|
self.fake_dev,
|
|
|
|
root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
prep_boot_part_uuid=None,
|
|
|
|
target_boot_mode='uefi'
|
|
|
|
)
|
|
|
|
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(efi_utils, 'manage_uefi', autospec=True)
|
2020-11-24 08:18:49 -08:00
|
|
|
@mock.patch.object(image, '_install_grub2', autospec=True)
|
|
|
|
def test__install_bootloader_uefi_ignores_grub_failure_api_override(
|
|
|
|
self, mock_grub2, mock_uefi,
|
|
|
|
mock_execute, mock_dispatch):
|
|
|
|
self.config(ignore_bootloader_failure=False)
|
|
|
|
mock_grub2.side_effect = OSError('meow')
|
|
|
|
mock_dispatch.side_effect = [
|
|
|
|
self.fake_dev, hardware.BootInfo(current_boot_mode='uefi')
|
|
|
|
]
|
|
|
|
mock_uefi.return_value = False
|
|
|
|
self.agent_extension.install_bootloader(
|
|
|
|
root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
target_boot_mode='uefi', ignore_bootloader_failure=True,
|
|
|
|
).join()
|
|
|
|
mock_dispatch.assert_any_call('get_os_install_device')
|
|
|
|
mock_dispatch.assert_any_call('get_boot_info')
|
|
|
|
self.assertEqual(2, mock_dispatch.call_count)
|
|
|
|
mock_grub2.assert_called_once_with(
|
|
|
|
self.fake_dev,
|
|
|
|
root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
prep_boot_part_uuid=None,
|
|
|
|
target_boot_mode='uefi'
|
|
|
|
)
|
|
|
|
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(efi_utils, 'manage_uefi', autospec=True)
|
2020-11-24 08:18:49 -08:00
|
|
|
@mock.patch.object(image, '_install_grub2', autospec=True)
|
|
|
|
def test__install_bootloader_uefi_grub_failure_api_override(
|
|
|
|
self, mock_grub2, mock_uefi,
|
|
|
|
mock_execute, mock_dispatch):
|
|
|
|
self.config(ignore_bootloader_failure=True)
|
|
|
|
mock_grub2.side_effect = OSError('meow')
|
|
|
|
mock_dispatch.side_effect = [
|
|
|
|
self.fake_dev, hardware.BootInfo(current_boot_mode='uefi')
|
|
|
|
]
|
|
|
|
mock_uefi.return_value = False
|
|
|
|
result = self.agent_extension.install_bootloader(
|
|
|
|
root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
target_boot_mode='uefi', ignore_bootloader_failure=False,
|
|
|
|
).join()
|
|
|
|
self.assertIsNotNone(result.command_error)
|
|
|
|
mock_dispatch.assert_any_call('get_os_install_device')
|
|
|
|
mock_dispatch.assert_any_call('get_boot_info')
|
2019-12-02 16:56:42 +01:00
|
|
|
self.assertEqual(2, mock_dispatch.call_count)
|
2015-03-12 09:15:49 +00:00
|
|
|
mock_grub2.assert_called_once_with(
|
|
|
|
self.fake_dev,
|
|
|
|
root_uuid=self.fake_root_uuid,
|
2018-07-11 13:35:54 +00:00
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
2019-08-06 13:52:13 +02:00
|
|
|
prep_boot_part_uuid=None,
|
|
|
|
target_boot_mode='uefi'
|
|
|
|
)
|
2018-07-11 13:35:54 +00:00
|
|
|
|
2020-10-07 12:06:42 +02:00
|
|
|
@mock.patch.object(image, '_install_grub2', autospec=True)
|
2021-05-10 12:43:17 +02:00
|
|
|
def test__install_bootloader_no_root(self, mock_grub2,
|
2020-10-07 12:06:42 +02:00
|
|
|
mock_execute, mock_dispatch):
|
|
|
|
mock_dispatch.side_effect = [
|
|
|
|
self.fake_dev, hardware.BootInfo(current_boot_mode='bios')
|
|
|
|
]
|
|
|
|
self.agent_extension.install_bootloader(
|
|
|
|
root_uuid='0x00000000').join()
|
|
|
|
mock_dispatch.assert_any_call('get_os_install_device')
|
|
|
|
mock_dispatch.assert_any_call('get_boot_info')
|
|
|
|
self.assertEqual(2, mock_dispatch.call_count)
|
|
|
|
self.assertFalse(mock_grub2.called)
|
|
|
|
|
2019-08-06 13:52:13 +02:00
|
|
|
@mock.patch.object(hardware, 'is_md_device', lambda *_: False)
|
2019-12-02 16:56:42 +01:00
|
|
|
@mock.patch.object(os.path, 'exists', lambda *_: False)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(efi_utils, '_get_efi_bootloaders', autospec=True)
|
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2021-08-27 13:28:41 +02:00
|
|
|
@mock.patch.object(disk_utils, 'find_efi_partition', autospec=False)
|
2019-12-02 16:56:42 +01:00
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
|
|
|
def test__uefi_bootloader_given_partition(
|
2022-05-04 14:45:33 +02:00
|
|
|
self, mkdir_mock, mock_utils_efi_part, mock_get_partition,
|
2021-05-10 12:43:17 +02:00
|
|
|
mock_efi_bl, mock_execute, mock_dispatch):
|
2019-12-02 16:56:42 +01:00
|
|
|
mock_dispatch.side_effect = [
|
|
|
|
self.fake_dev, hardware.BootInfo(current_boot_mode='uefi')
|
|
|
|
]
|
2022-05-04 14:45:33 +02:00
|
|
|
mock_get_partition.return_value = self.fake_efi_system_part
|
2021-05-26 10:41:40 +12:00
|
|
|
mock_efi_bl.return_value = ['EFI/BOOT/BOOTX64.EFI']
|
2022-05-04 14:45:33 +02:00
|
|
|
mock_utils_efi_part.return_value = None
|
2019-12-02 16:56:42 +01:00
|
|
|
|
|
|
|
mock_execute.side_effect = iter([('', ''), ('', ''),
|
2020-02-08 07:18:12 -08:00
|
|
|
('', ''), ('', ''),
|
2023-04-07 07:32:44 -07:00
|
|
|
(EFI_RESULT, ''), (EFI_RESULT, ''),
|
2019-12-02 16:56:42 +01:00
|
|
|
('', ''), ('', '')])
|
|
|
|
|
|
|
|
expected = [mock.call('efibootmgr', '--version'),
|
2022-02-14 11:50:49 +01:00
|
|
|
mock.call('partx', '-av', '/dev/fake', attempts=3,
|
2020-02-08 07:18:12 -08:00
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('udevadm', 'settle'),
|
2019-12-02 16:56:42 +01:00
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
self.fake_dir + '/boot/efi'),
|
2023-04-07 07:32:44 -07:00
|
|
|
mock.call('efibootmgr', '-v', binary=True),
|
2021-08-03 12:10:44 +01:00
|
|
|
mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
|
2019-12-02 16:56:42 +01:00
|
|
|
'-p', '1', '-w',
|
|
|
|
'-L', 'ironic1', '-l',
|
2023-04-07 07:32:44 -07:00
|
|
|
'\\EFI\\BOOT\\BOOTX64.EFI', binary=True),
|
2019-12-02 16:56:42 +01:00
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('sync')]
|
|
|
|
|
|
|
|
self.agent_extension.install_bootloader(
|
|
|
|
root_uuid=self.fake_root_uuid,
|
2020-06-08 15:10:05 +02:00
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid).join()
|
2019-12-02 16:56:42 +01:00
|
|
|
|
|
|
|
mock_dispatch.assert_any_call('get_os_install_device')
|
|
|
|
mock_dispatch.assert_any_call('get_boot_info')
|
|
|
|
mkdir_mock.assert_called_once_with(self.fake_dir + '/boot/efi')
|
|
|
|
mock_efi_bl.assert_called_once_with(self.fake_dir + '/boot/efi')
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
mock_utils_efi_part.assert_called_once_with(self.fake_dev)
|
2020-02-08 07:18:12 -08:00
|
|
|
self.assertEqual(8, mock_execute.call_count)
|
2019-12-02 16:56:42 +01:00
|
|
|
|
2019-08-06 13:52:13 +02:00
|
|
|
@mock.patch.object(hardware, 'is_md_device', lambda *_: False)
|
2019-12-02 16:56:42 +01:00
|
|
|
@mock.patch.object(os.path, 'exists', lambda *_: False)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(efi_utils, '_get_efi_bootloaders', autospec=True)
|
2022-05-04 14:45:33 +02:00
|
|
|
@mock.patch.object(efi_utils, 'get_partition_path_by_number',
|
|
|
|
autospec=True)
|
2021-08-27 13:28:41 +02:00
|
|
|
@mock.patch.object(disk_utils, 'find_efi_partition', autospec=True)
|
2019-12-02 16:56:42 +01:00
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
|
|
|
def test__uefi_bootloader_find_partition(
|
2022-05-04 14:45:33 +02:00
|
|
|
self, mkdir_mock, mock_utils_efi_part, mock_get_part_path,
|
2021-05-10 12:43:17 +02:00
|
|
|
mock_efi_bl, mock_execute, mock_dispatch):
|
2019-12-02 16:56:42 +01:00
|
|
|
mock_dispatch.side_effect = [
|
|
|
|
self.fake_dev, hardware.BootInfo(current_boot_mode='uefi')
|
|
|
|
]
|
2022-05-04 14:45:33 +02:00
|
|
|
mock_get_part_path.return_value = self.fake_efi_system_part
|
2021-11-19 14:48:38 +01:00
|
|
|
mock_utils_efi_part.return_value = {'number': '1'}
|
2021-05-26 10:41:40 +12:00
|
|
|
mock_efi_bl.return_value = ['EFI/BOOT/BOOTX64.EFI']
|
2019-12-02 16:56:42 +01:00
|
|
|
mock_execute.side_effect = iter([('', ''), ('', ''),
|
2020-02-08 07:18:12 -08:00
|
|
|
('', ''), ('', ''),
|
2023-04-07 07:32:44 -07:00
|
|
|
(EFI_RESULT, ''), (EFI_RESULT, ''),
|
2019-12-02 16:56:42 +01:00
|
|
|
('', ''), ('', '')])
|
|
|
|
|
|
|
|
expected = [mock.call('efibootmgr', '--version'),
|
2022-02-14 11:50:49 +01:00
|
|
|
mock.call('partx', '-av', '/dev/fake', attempts=3,
|
2020-02-08 07:18:12 -08:00
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('udevadm', 'settle'),
|
2019-12-02 16:56:42 +01:00
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
self.fake_dir + '/boot/efi'),
|
2023-04-07 07:32:44 -07:00
|
|
|
mock.call('efibootmgr', '-v', binary=True),
|
2021-08-03 12:10:44 +01:00
|
|
|
mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
|
2019-12-02 16:56:42 +01:00
|
|
|
'-p', '1', '-w',
|
|
|
|
'-L', 'ironic1', '-l',
|
2023-04-07 07:32:44 -07:00
|
|
|
'\\EFI\\BOOT\\BOOTX64.EFI', binary=True),
|
2019-12-02 16:56:42 +01:00
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('sync')]
|
|
|
|
|
|
|
|
self.agent_extension.install_bootloader(
|
|
|
|
root_uuid=self.fake_root_uuid,
|
2020-06-08 15:10:05 +02:00
|
|
|
efi_system_part_uuid=None).join()
|
2019-12-02 16:56:42 +01:00
|
|
|
|
|
|
|
mock_dispatch.assert_any_call('get_os_install_device')
|
|
|
|
mock_dispatch.assert_any_call('get_boot_info')
|
|
|
|
mkdir_mock.assert_called_once_with(self.fake_dir + '/boot/efi')
|
|
|
|
mock_efi_bl.assert_called_once_with(self.fake_dir + '/boot/efi')
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
mock_utils_efi_part.assert_called_once_with(self.fake_dev)
|
2020-02-08 07:18:12 -08:00
|
|
|
self.assertEqual(8, mock_execute.call_count)
|
2019-12-02 16:56:42 +01:00
|
|
|
|
2019-08-06 13:52:13 +02:00
|
|
|
@mock.patch.object(hardware, 'is_md_device', lambda *_: False)
|
2019-12-02 16:56:42 +01:00
|
|
|
@mock.patch.object(os.path, 'exists', lambda *_: False)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(efi_utils, '_get_efi_bootloaders', autospec=True)
|
2022-05-04 14:45:33 +02:00
|
|
|
@mock.patch.object(efi_utils, 'get_partition_path_by_number',
|
|
|
|
autospec=True)
|
2021-08-27 13:28:41 +02:00
|
|
|
@mock.patch.object(disk_utils, 'find_efi_partition', autospec=True)
|
2019-12-02 16:56:42 +01:00
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
|
|
|
def test__uefi_bootloader_with_entry_removal(
|
2022-05-04 14:45:33 +02:00
|
|
|
self, mkdir_mock, mock_utils_efi_part, mock_get_part_path,
|
2021-05-10 12:43:17 +02:00
|
|
|
mock_efi_bl, mock_execute, mock_dispatch):
|
2019-12-02 16:56:42 +01:00
|
|
|
mock_dispatch.side_effect = [
|
|
|
|
self.fake_dev, hardware.BootInfo(current_boot_mode='uefi')
|
|
|
|
]
|
2022-05-04 14:45:33 +02:00
|
|
|
mock_get_part_path.return_value = self.fake_efi_system_part
|
2021-11-19 14:48:38 +01:00
|
|
|
mock_utils_efi_part.return_value = {'number': '1'}
|
2021-05-26 10:41:40 +12:00
|
|
|
mock_efi_bl.return_value = ['EFI/BOOT/BOOTX64.EFI']
|
2021-10-28 11:41:00 -07:00
|
|
|
stdout_msg = """
|
|
|
|
BootCurrent: 0001
|
|
|
|
Timeout: 0 seconds
|
|
|
|
BootOrder: 0000,00001
|
2021-11-04 09:42:04 -07:00
|
|
|
Boot0000 ironic1 HD(1,GPT,4f3c6294-bf9b-4208-9808-be45dfc34b5c)File(\EFI\Boot\BOOTX64.EFI)
|
|
|
|
Boot0001 ironic2 HD(1,GPT,4f3c6294-bf9b-4208-9808-111111111112)File(\EFI\Boot\BOOTX64.EFI)
|
|
|
|
Boot0002 VENDMAGIC FvFile(9f3c6294-bf9b-4208-9808-be45dfc34b51)
|
2021-10-28 11:41:00 -07:00
|
|
|
""" # noqa This is a giant literal string for testing.
|
2023-04-07 07:32:44 -07:00
|
|
|
stdout_msg = stdout_msg.encode('utf-16')
|
2019-12-02 16:56:42 +01:00
|
|
|
mock_execute.side_effect = iter([('', ''), ('', ''),
|
2020-02-08 07:18:12 -08:00
|
|
|
('', ''), ('', ''),
|
2023-04-07 07:32:44 -07:00
|
|
|
(stdout_msg, ''), (EFI_RESULT, ''),
|
|
|
|
(EFI_RESULT, ''), (EFI_RESULT, ''),
|
2019-12-02 16:56:42 +01:00
|
|
|
('', ''), ('', '')])
|
|
|
|
|
|
|
|
expected = [mock.call('efibootmgr', '--version'),
|
2022-02-14 11:50:49 +01:00
|
|
|
mock.call('partx', '-av', '/dev/fake', attempts=3,
|
2020-02-08 07:18:12 -08:00
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('udevadm', 'settle'),
|
2019-12-02 16:56:42 +01:00
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
self.fake_dir + '/boot/efi'),
|
2023-04-07 07:32:44 -07:00
|
|
|
mock.call('efibootmgr', '-v', binary=True),
|
|
|
|
mock.call('efibootmgr', '-b', '0000', '-B', binary=True),
|
2021-08-03 12:10:44 +01:00
|
|
|
mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
|
2019-12-02 16:56:42 +01:00
|
|
|
'-p', '1', '-w',
|
|
|
|
'-L', 'ironic1', '-l',
|
2023-04-07 07:32:44 -07:00
|
|
|
'\\EFI\\BOOT\\BOOTX64.EFI', binary=True),
|
2019-12-02 16:56:42 +01:00
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('sync')]
|
|
|
|
|
|
|
|
self.agent_extension.install_bootloader(
|
|
|
|
root_uuid=self.fake_root_uuid,
|
2020-06-08 15:10:05 +02:00
|
|
|
efi_system_part_uuid=None).join()
|
2019-12-02 16:56:42 +01:00
|
|
|
|
|
|
|
mock_dispatch.assert_any_call('get_os_install_device')
|
|
|
|
mock_dispatch.assert_any_call('get_boot_info')
|
|
|
|
mkdir_mock.assert_called_once_with(self.fake_dir + '/boot/efi')
|
|
|
|
mock_efi_bl.assert_called_once_with(self.fake_dir + '/boot/efi')
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
mock_utils_efi_part.assert_called_once_with(self.fake_dev)
|
2021-10-28 11:41:00 -07:00
|
|
|
self.assertEqual(9, mock_execute.call_count)
|
2019-12-02 16:56:42 +01:00
|
|
|
|
2021-11-04 09:42:04 -07:00
|
|
|
@mock.patch.object(hardware, 'is_md_device', lambda *_: False)
|
|
|
|
@mock.patch.object(os.path, 'exists', lambda *_: False)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(efi_utils, '_get_efi_bootloaders', autospec=True)
|
2022-05-04 14:45:33 +02:00
|
|
|
@mock.patch.object(efi_utils, 'get_partition_path_by_number',
|
|
|
|
autospec=True)
|
2021-08-27 13:28:41 +02:00
|
|
|
@mock.patch.object(disk_utils, 'find_efi_partition', autospec=True)
|
2021-11-04 09:42:04 -07:00
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
|
|
|
def test__uefi_bootloader_with_entry_removal_lenovo(
|
2022-05-04 14:45:33 +02:00
|
|
|
self, mkdir_mock, mock_utils_efi_part, mock_get_part_path,
|
2021-11-04 09:42:04 -07:00
|
|
|
mock_efi_bl, mock_execute, mock_dispatch):
|
|
|
|
mock_dispatch.side_effect = [
|
|
|
|
self.fake_dev, hardware.BootInfo(current_boot_mode='uefi')
|
|
|
|
]
|
2022-05-04 14:45:33 +02:00
|
|
|
mock_get_part_path.return_value = self.fake_efi_system_part
|
2021-11-19 14:48:38 +01:00
|
|
|
mock_utils_efi_part.return_value = {'number': '1'}
|
2021-11-04 09:42:04 -07:00
|
|
|
mock_efi_bl.return_value = ['EFI/BOOT/BOOTX64.EFI']
|
|
|
|
# NOTE(TheJulia): This test string was derived from a lenovo SR650
|
|
|
|
# which does do some weird things with additional entries.
|
|
|
|
# most notabley
|
|
|
|
stdout_msg = """
|
|
|
|
BootCurrent: 0000
|
|
|
|
Timeout: 1 seconds
|
|
|
|
BootOrder: 0000,0003,0002,0001
|
|
|
|
Boot0000* ironic1 HD(1,GPT,55db8d03-c8f6-4a5b-9155-790dddc348fa,0x800,0x64000)/File(\EFI\boot\shimx64.efi)
|
|
|
|
Boot0001* CD/DVD Rom VenHw(1fad3248-0000-7950-2166-a1e506fdb83a,02000000)..GO
|
|
|
|
Boot0002* Hard Disk VenHw(1fad3248-0000-7950-2166-a1e506fdb83a,01000000)..GO..NO..........V.U.E.F.I.:. . . .S.C.S.I. .H.a.r.d. .D.r.i.v.e........A....................................*..............@.........U..[J.Uy...H.......BO
|
|
|
|
Boot0003* Network VenHw(1fad3248-0000-7950-2166-a1e506fdb83a,05000000)..GO..NO............U.E.F.I.:. . . .S.L.O.T.2. .(.2.F./.0./.0.). .P.X.E. .I.P.4. . .Q.L.o.g.i.c. .Q.L.4.1.2.6.2. .P.C.I.e. .2.5.G.b. .2.-.P.o.r.t. .S.F.P.2.8. .E.t.h.e.r.n.e.t. .A.d.a.p.t.e.r. .-. .P.X.E........A....................%.4..Z...............................................................Gd-.;.A..MQ..L.P.X.E. .I.P.4. .Q.L.o.g.i.c. .Q.L.4.1.2.6.2. .P.C.I.e. .2.5.G.b. .2.-.P.o.r.t. .S.F.P.2.8. .E.t.h.e.r.n.e.t. .A.d.a.p.t.e.r. .-. .P.X.E.......BO..NO............U.E.F.I.:. . . .S.L.O.T.1. .(.3.0./.0./.0.). .P.X.E. .I.P.4. . .Q.L.o.g.i.c. .Q.L.4.1.2.6.2. .P.C.I.e. .2.5.G.b. .2.-.P.o.r.t. .S.F.P.2.8. .E.t.h.e.r.n.e.t. .A.d.a.p.t.e.r. .-.
|
|
|
|
Boot0004* ironic1 HD(1,GPT,55db8d03-c8f6-4a5b-9155-790dddc348fa,0x800,0x64000)/File(\EFI\boot\shimx64.efi)
|
|
|
|
""" # noqa This is a giant literal string for testing.
|
2023-04-07 07:32:44 -07:00
|
|
|
stdout_msg = stdout_msg.encode('utf-16')
|
2021-11-04 09:42:04 -07:00
|
|
|
mock_execute.side_effect = iter([('', ''), ('', ''),
|
|
|
|
('', ''), ('', ''),
|
|
|
|
(stdout_msg, ''), ('', ''),
|
|
|
|
('', ''), ('', ''),
|
|
|
|
('', ''), ('', '')])
|
|
|
|
expected = [mock.call('efibootmgr', '--version'),
|
2022-02-14 11:50:49 +01:00
|
|
|
mock.call('partx', '-av', '/dev/fake', attempts=3,
|
2021-11-04 09:42:04 -07:00
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('udevadm', 'settle'),
|
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
self.fake_dir + '/boot/efi'),
|
2023-04-07 07:32:44 -07:00
|
|
|
mock.call('efibootmgr', '-v', binary=True),
|
|
|
|
mock.call('efibootmgr', '-b', '0000', '-B', binary=True),
|
|
|
|
mock.call('efibootmgr', '-b', '0004', '-B', binary=True),
|
2021-11-04 09:42:04 -07:00
|
|
|
mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
|
|
|
|
'-p', '1', '-w',
|
|
|
|
'-L', 'ironic1', '-l',
|
2023-04-07 07:32:44 -07:00
|
|
|
'\\EFI\\BOOT\\BOOTX64.EFI', binary=True),
|
2021-11-04 09:42:04 -07:00
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('sync')]
|
|
|
|
|
|
|
|
self.agent_extension.install_bootloader(
|
|
|
|
root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=None).join()
|
|
|
|
|
|
|
|
mock_dispatch.assert_any_call('get_os_install_device')
|
|
|
|
mock_dispatch.assert_any_call('get_boot_info')
|
|
|
|
mkdir_mock.assert_called_once_with(self.fake_dir + '/boot/efi')
|
|
|
|
mock_efi_bl.assert_called_once_with(self.fake_dir + '/boot/efi')
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
mock_utils_efi_part.assert_called_once_with(self.fake_dev)
|
|
|
|
self.assertEqual(10, mock_execute.call_count)
|
|
|
|
|
2019-08-06 13:52:13 +02:00
|
|
|
@mock.patch.object(hardware, 'is_md_device', lambda *_: False)
|
2019-12-02 16:56:42 +01:00
|
|
|
@mock.patch.object(os.path, 'exists', lambda *_: False)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(efi_utils, '_get_efi_bootloaders', autospec=True)
|
2022-05-04 14:45:33 +02:00
|
|
|
@mock.patch.object(efi_utils, 'get_partition_path_by_number',
|
|
|
|
autospec=True)
|
2021-08-27 13:28:41 +02:00
|
|
|
@mock.patch.object(disk_utils, 'find_efi_partition', autospec=True)
|
2019-12-02 16:56:42 +01:00
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
|
|
|
def test__add_multi_bootloaders(
|
2022-05-04 14:45:33 +02:00
|
|
|
self, mkdir_mock, mock_utils_efi_part, mock_get_part_path,
|
2021-05-10 12:43:17 +02:00
|
|
|
mock_efi_bl, mock_execute, mock_dispatch):
|
2019-12-02 16:56:42 +01:00
|
|
|
mock_dispatch.side_effect = [
|
|
|
|
self.fake_dev, hardware.BootInfo(current_boot_mode='uefi')
|
|
|
|
]
|
2022-05-04 14:45:33 +02:00
|
|
|
mock_get_part_path.return_value = self.fake_efi_system_part
|
2021-11-19 14:48:38 +01:00
|
|
|
mock_utils_efi_part.return_value = {'number': '1'}
|
2021-05-26 10:41:40 +12:00
|
|
|
mock_efi_bl.return_value = ['EFI/BOOT/BOOTX64.EFI',
|
|
|
|
'WINDOWS/system32/winload.efi']
|
2019-12-02 16:56:42 +01:00
|
|
|
|
|
|
|
mock_execute.side_effect = iter([('', ''), ('', ''),
|
2020-02-08 07:18:12 -08:00
|
|
|
('', ''), ('', ''),
|
2023-04-07 07:32:44 -07:00
|
|
|
(EFI_RESULT, ''), (EFI_RESULT, ''),
|
|
|
|
(EFI_RESULT, ''), ('', ''),
|
2019-12-02 16:56:42 +01:00
|
|
|
('', '')])
|
|
|
|
|
|
|
|
expected = [mock.call('efibootmgr', '--version'),
|
2022-02-14 11:50:49 +01:00
|
|
|
mock.call('partx', '-av', '/dev/fake', attempts=3,
|
2020-02-08 07:18:12 -08:00
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('udevadm', 'settle'),
|
2019-12-02 16:56:42 +01:00
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
self.fake_dir + '/boot/efi'),
|
2023-04-07 07:32:44 -07:00
|
|
|
mock.call('efibootmgr', '-v', binary=True),
|
2021-08-03 12:10:44 +01:00
|
|
|
mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
|
2019-12-02 16:56:42 +01:00
|
|
|
'-p', '1', '-w',
|
|
|
|
'-L', 'ironic1', '-l',
|
2023-04-07 07:32:44 -07:00
|
|
|
'\\EFI\\BOOT\\BOOTX64.EFI', binary=True),
|
2021-08-03 12:10:44 +01:00
|
|
|
mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
|
2019-12-02 16:56:42 +01:00
|
|
|
'-p', '1', '-w',
|
|
|
|
'-L', 'ironic2', '-l',
|
2023-04-07 07:32:44 -07:00
|
|
|
'\\WINDOWS\\system32\\winload.efi', binary=True),
|
2019-12-02 16:56:42 +01:00
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('sync')]
|
|
|
|
|
|
|
|
self.agent_extension.install_bootloader(
|
|
|
|
root_uuid=self.fake_root_uuid,
|
2020-06-08 15:10:05 +02:00
|
|
|
efi_system_part_uuid=None).join()
|
2019-12-02 16:56:42 +01:00
|
|
|
|
|
|
|
mock_dispatch.assert_any_call('get_os_install_device')
|
|
|
|
mock_dispatch.assert_any_call('get_boot_info')
|
|
|
|
mkdir_mock.assert_called_once_with(self.fake_dir + '/boot/efi')
|
|
|
|
mock_efi_bl.assert_called_once_with(self.fake_dir + '/boot/efi')
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
mock_utils_efi_part.assert_called_once_with(self.fake_dev)
|
2020-02-08 07:18:12 -08:00
|
|
|
self.assertEqual(9, mock_execute.call_count)
|
2019-12-02 16:56:42 +01:00
|
|
|
|
2018-07-11 13:35:54 +00:00
|
|
|
@mock.patch.object(image, '_install_grub2', autospec=True)
|
2021-05-10 12:43:17 +02:00
|
|
|
def test__install_bootloader_prep(self, mock_grub2,
|
2019-12-02 16:56:42 +01:00
|
|
|
mock_execute, mock_dispatch):
|
|
|
|
mock_dispatch.side_effect = [
|
|
|
|
self.fake_dev, hardware.BootInfo(current_boot_mode='bios')
|
|
|
|
]
|
2018-07-11 13:35:54 +00:00
|
|
|
self.agent_extension.install_bootloader(
|
|
|
|
root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=None,
|
2020-06-08 15:10:05 +02:00
|
|
|
prep_boot_part_uuid=self.fake_prep_boot_part_uuid).join()
|
2019-12-02 16:56:42 +01:00
|
|
|
mock_dispatch.assert_any_call('get_os_install_device')
|
|
|
|
mock_dispatch.assert_any_call('get_boot_info')
|
|
|
|
self.assertEqual(2, mock_dispatch.call_count)
|
2018-07-11 13:35:54 +00:00
|
|
|
mock_grub2.assert_called_once_with(
|
|
|
|
self.fake_dev,
|
|
|
|
root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=None,
|
2019-08-06 13:52:13 +02:00
|
|
|
prep_boot_part_uuid=self.fake_prep_boot_part_uuid,
|
|
|
|
target_boot_mode='bios'
|
|
|
|
)
|
2020-07-20 14:24:06 -07:00
|
|
|
|
2019-08-06 13:52:13 +02:00
|
|
|
@mock.patch.object(hardware, 'is_md_device', lambda *_: False)
|
2020-02-21 05:24:05 -06:00
|
|
|
@mock.patch.object(os.path, 'exists', lambda *_: False)
|
2021-05-10 12:43:17 +02:00
|
|
|
def test_install_bootloader_failure(self, mock_execute, mock_dispatch):
|
2020-02-21 05:24:05 -06:00
|
|
|
mock_dispatch.side_effect = [
|
|
|
|
self.fake_dev, hardware.BootInfo(current_boot_mode='uefi')
|
|
|
|
]
|
|
|
|
mock_execute.side_effect = FileNotFoundError
|
2020-06-08 15:10:05 +02:00
|
|
|
result = self.agent_extension.install_bootloader(
|
|
|
|
root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=None).join()
|
|
|
|
self.assertIsNotNone(result.command_error)
|
2020-02-21 05:24:05 -06:00
|
|
|
expected = [mock.call('efibootmgr', '--version')]
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
|
2020-09-16 13:10:13 -07:00
|
|
|
@mock.patch.object(os.path, 'exists', lambda *_: True)
|
2019-08-29 16:22:50 -04:00
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
|
2020-08-26 08:35:33 -07:00
|
|
|
@mock.patch.object(image, '_append_uefi_to_fstab', autospec=True)
|
2019-02-26 17:56:20 +01:00
|
|
|
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
2019-10-17 11:14:04 +00:00
|
|
|
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(os, 'environ', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2015-03-12 09:15:49 +00:00
|
|
|
def test__install_grub2(self, mock_get_part_uuid, environ_mock,
|
2019-10-17 11:14:04 +00:00
|
|
|
mock_md_get_raid_devices, mock_is_md_device,
|
2020-08-26 08:35:33 -07:00
|
|
|
mock_append_to_fstab, mock_execute,
|
|
|
|
mock_dispatch):
|
2015-03-12 09:15:49 +00:00
|
|
|
mock_get_part_uuid.return_value = self.fake_root_part
|
|
|
|
environ_mock.get.return_value = '/sbin'
|
2019-08-29 16:22:50 -04:00
|
|
|
mock_is_md_device.return_value = False
|
2019-10-17 11:14:04 +00:00
|
|
|
mock_md_get_raid_devices.return_value = {}
|
2015-02-19 13:42:39 +00:00
|
|
|
image._install_grub2(self.fake_dev, self.fake_root_uuid)
|
|
|
|
|
|
|
|
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/dev'),
|
2015-02-19 13:42:39 +00:00
|
|
|
mock.call('mount', '-o', 'bind', '/dev',
|
|
|
|
self.fake_dir + '/dev'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/proc'),
|
2015-02-19 13:42:39 +00:00
|
|
|
mock.call('mount', '-o', 'bind', '/proc',
|
|
|
|
self.fake_dir + '/proc'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/run'),
|
2019-04-24 23:25:19 +01:00
|
|
|
mock.call('mount', '-o', 'bind', '/run',
|
|
|
|
self.fake_dir + '/run'),
|
2015-10-06 14:50:55 -04:00
|
|
|
mock.call('mount', '-t', 'sysfs', 'none',
|
|
|
|
self.fake_dir + '/sys'),
|
2020-05-05 16:45:51 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c "mount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2017-01-16 21:32:37 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
2020-09-16 13:10:13 -07:00
|
|
|
'"grub2-install %s"' %
|
2015-10-02 10:01:00 -07:00
|
|
|
(self.fake_dir, self.fake_dev)), shell=True,
|
2019-08-06 13:52:13 +02:00
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2017-01-16 21:32:37 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
2020-09-16 13:10:13 -07:00
|
|
|
'"grub2-mkconfig -o '
|
|
|
|
'/boot/grub2/grub.cfg"' % self.fake_dir),
|
2015-03-12 09:15:49 +00:00
|
|
|
shell=True,
|
2019-08-06 13:52:13 +02:00
|
|
|
env_variables={
|
2020-09-16 13:10:13 -07:00
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
2020-08-25 16:14:45 -07:00
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
2020-09-16 13:10:13 -07:00
|
|
|
use_standard_locale=True),
|
2020-05-05 16:45:51 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2015-02-19 13:42:39 +00:00
|
|
|
mock.call('umount', self.fake_dir + '/dev',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/proc',
|
|
|
|
attempts=3, delay_on_retry=True),
|
2019-04-24 23:25:19 +01:00
|
|
|
mock.call('umount', self.fake_dir + '/run',
|
|
|
|
attempts=3, delay_on_retry=True),
|
2015-10-06 14:50:55 -04:00
|
|
|
mock.call('umount', self.fake_dir + '/sys',
|
|
|
|
attempts=3, delay_on_retry=True),
|
2015-02-19 13:42:39 +00:00
|
|
|
mock.call('umount', self.fake_dir, attempts=3,
|
|
|
|
delay_on_retry=True)]
|
|
|
|
mock_execute.assert_has_calls(expected)
|
2015-03-12 09:15:49 +00:00
|
|
|
mock_get_part_uuid.assert_called_once_with(self.fake_dev,
|
|
|
|
uuid=self.fake_root_uuid)
|
|
|
|
self.assertFalse(mock_dispatch.called)
|
2020-08-26 08:35:33 -07:00
|
|
|
self.assertFalse(mock_append_to_fstab.called)
|
2015-03-12 09:15:49 +00:00
|
|
|
|
2019-08-29 16:22:50 -04:00
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
|
2019-02-26 17:56:20 +01:00
|
|
|
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
2019-10-17 11:14:04 +00:00
|
|
|
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
|
2018-07-11 13:35:54 +00:00
|
|
|
@mock.patch.object(os, 'environ', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2018-07-11 13:35:54 +00:00
|
|
|
def test__install_grub2_prep(self, mock_get_part_uuid, environ_mock,
|
2019-10-17 11:14:04 +00:00
|
|
|
mock_md_get_raid_devices, mock_is_md_device,
|
|
|
|
mock_execute, mock_dispatch):
|
2018-07-11 13:35:54 +00:00
|
|
|
mock_get_part_uuid.side_effect = [self.fake_root_part,
|
|
|
|
self.fake_prep_boot_part]
|
|
|
|
environ_mock.get.return_value = '/sbin'
|
2019-08-29 16:22:50 -04:00
|
|
|
mock_is_md_device.return_value = False
|
2019-10-17 11:14:04 +00:00
|
|
|
mock_md_get_raid_devices.return_value = {}
|
2018-07-11 13:35:54 +00:00
|
|
|
image._install_grub2(self.fake_dev, self.fake_root_uuid,
|
|
|
|
prep_boot_part_uuid=self.fake_prep_boot_part_uuid)
|
|
|
|
|
|
|
|
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/dev'),
|
2018-07-11 13:35:54 +00:00
|
|
|
mock.call('mount', '-o', 'bind', '/dev',
|
|
|
|
self.fake_dir + '/dev'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/proc'),
|
2018-07-11 13:35:54 +00:00
|
|
|
mock.call('mount', '-o', 'bind', '/proc',
|
|
|
|
self.fake_dir + '/proc'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/run'),
|
2019-04-24 23:25:19 +01:00
|
|
|
mock.call('mount', '-o', 'bind', '/run',
|
|
|
|
self.fake_dir + '/run'),
|
2018-07-11 13:35:54 +00:00
|
|
|
mock.call('mount', '-t', 'sysfs', 'none',
|
|
|
|
self.fake_dir + '/sys'),
|
2020-05-05 16:45:51 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c "mount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2018-07-11 13:35:54 +00:00
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub-install %s"' %
|
|
|
|
(self.fake_dir, self.fake_prep_boot_part)),
|
|
|
|
shell=True,
|
2019-08-06 13:52:13 +02:00
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2018-07-11 13:35:54 +00:00
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub-mkconfig -o '
|
|
|
|
'/boot/grub/grub.cfg"' % self.fake_dir),
|
|
|
|
shell=True,
|
2019-08-06 13:52:13 +02:00
|
|
|
env_variables={
|
2020-09-16 13:10:13 -07:00
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
2020-08-25 16:14:45 -07:00
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
2020-09-16 13:10:13 -07:00
|
|
|
use_standard_locale=True),
|
2020-05-05 16:45:51 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2018-07-11 13:35:54 +00:00
|
|
|
mock.call('umount', self.fake_dir + '/dev',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/proc',
|
|
|
|
attempts=3, delay_on_retry=True),
|
2019-04-24 23:25:19 +01:00
|
|
|
mock.call('umount', self.fake_dir + '/run',
|
|
|
|
attempts=3, delay_on_retry=True),
|
2018-07-11 13:35:54 +00:00
|
|
|
mock.call('umount', self.fake_dir + '/sys',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir, attempts=3,
|
|
|
|
delay_on_retry=True)]
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_root_uuid)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_prep_boot_part_uuid)
|
|
|
|
self.assertFalse(mock_dispatch.called)
|
|
|
|
|
2021-06-11 18:20:49 +02:00
|
|
|
@mock.patch.object(os.path, 'ismount', lambda *_: False)
|
2019-12-02 16:56:42 +01:00
|
|
|
@mock.patch.object(os.path, 'exists', lambda *_: False)
|
2019-08-29 16:22:50 -04:00
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: True)
|
2020-08-26 08:35:33 -07:00
|
|
|
@mock.patch.object(image, '_append_uefi_to_fstab', autospec=True)
|
2019-02-26 17:56:20 +01:00
|
|
|
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
2019-10-17 11:14:04 +00:00
|
|
|
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(os, 'environ', autospec=True)
|
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2015-03-12 09:15:49 +00:00
|
|
|
def test__install_grub2_uefi(self, mock_get_part_uuid, mkdir_mock,
|
2019-10-17 11:14:04 +00:00
|
|
|
environ_mock, mock_md_get_raid_devices,
|
2020-08-26 08:35:33 -07:00
|
|
|
mock_is_md_device, mock_append_to_fstab,
|
|
|
|
mock_execute, mock_dispatch):
|
2015-03-12 09:15:49 +00:00
|
|
|
mock_get_part_uuid.side_effect = [self.fake_root_part,
|
|
|
|
self.fake_efi_system_part]
|
|
|
|
environ_mock.get.return_value = '/sbin'
|
2019-02-26 17:56:20 +01:00
|
|
|
mock_is_md_device.return_value = False
|
2019-10-17 11:14:04 +00:00
|
|
|
mock_md_get_raid_devices.return_value = {}
|
2015-03-12 09:15:49 +00:00
|
|
|
|
|
|
|
image._install_grub2(
|
|
|
|
self.fake_dev, root_uuid=self.fake_root_uuid,
|
2019-08-06 13:52:13 +02:00
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
target_boot_mode='uefi')
|
2015-03-12 09:15:49 +00:00
|
|
|
|
|
|
|
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/dev'),
|
2015-03-12 09:15:49 +00:00
|
|
|
mock.call('mount', '-o', 'bind', '/dev',
|
|
|
|
self.fake_dir + '/dev'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/proc'),
|
2015-03-12 09:15:49 +00:00
|
|
|
mock.call('mount', '-o', 'bind', '/proc',
|
|
|
|
self.fake_dir + '/proc'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/run'),
|
2019-04-24 23:25:19 +01:00
|
|
|
mock.call('mount', '-o', 'bind', '/run',
|
|
|
|
self.fake_dir + '/run'),
|
2015-10-06 14:50:55 -04:00
|
|
|
mock.call('mount', '-t', 'sysfs', 'none',
|
|
|
|
self.fake_dir + '/sys'),
|
2021-06-11 18:20:49 +02:00
|
|
|
mock.call('mount', '/dev/fake2', self.fake_dir),
|
2020-05-05 16:45:51 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c "mount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2015-03-12 09:15:49 +00:00
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
self.fake_dir + '/boot/efi'),
|
2019-08-06 13:52:13 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c "grub-install"' %
|
|
|
|
self.fake_dir), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2017-01-16 21:32:37 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
2019-08-06 13:52:13 +02:00
|
|
|
'"grub-install --removable"' %
|
|
|
|
self.fake_dir), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call(
|
|
|
|
'umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
'/tmp/fake-dir/boot/efi'),
|
2017-01-16 21:32:37 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
2017-09-14 07:05:25 -06:00
|
|
|
'"grub-mkconfig -o '
|
2015-03-12 09:15:49 +00:00
|
|
|
'/boot/grub/grub.cfg"' % self.fake_dir),
|
|
|
|
shell=True,
|
2019-08-06 13:52:13 +02:00
|
|
|
env_variables={
|
2020-09-16 13:10:13 -07:00
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
2020-08-25 16:14:45 -07:00
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
2020-09-16 13:10:13 -07:00
|
|
|
use_standard_locale=True),
|
2015-03-12 09:15:49 +00:00
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
2020-05-05 16:45:51 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2015-03-12 09:15:49 +00:00
|
|
|
mock.call('umount', self.fake_dir + '/dev',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/proc',
|
|
|
|
attempts=3, delay_on_retry=True),
|
2019-04-24 23:25:19 +01:00
|
|
|
mock.call('umount', self.fake_dir + '/run',
|
|
|
|
attempts=3, delay_on_retry=True),
|
2015-10-06 14:50:55 -04:00
|
|
|
mock.call('umount', self.fake_dir + '/sys',
|
|
|
|
attempts=3, delay_on_retry=True),
|
2015-03-12 09:15:49 +00:00
|
|
|
mock.call('umount', self.fake_dir, attempts=3,
|
|
|
|
delay_on_retry=True)]
|
|
|
|
mkdir_mock.assert_called_once_with(self.fake_dir + '/boot/efi')
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_root_uuid)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_efi_system_part_uuid)
|
2015-02-19 13:42:39 +00:00
|
|
|
self.assertFalse(mock_dispatch.called)
|
2020-08-26 08:35:33 -07:00
|
|
|
mock_append_to_fstab.assert_called_with(self.fake_dir,
|
|
|
|
self.fake_efi_system_part_uuid)
|
|
|
|
|
2022-04-07 15:15:17 -07:00
|
|
|
@mock.patch.object(hardware, 'get_multipath_status', lambda *_: False)
|
2021-06-11 18:20:49 +02:00
|
|
|
@mock.patch.object(os.path, 'ismount', lambda *_: False)
|
2020-08-26 08:35:33 -07:00
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: True)
|
|
|
|
@mock.patch.object(os.path, 'exists', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
|
|
|
|
@mock.patch.object(os, 'environ', autospec=True)
|
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2020-08-26 08:35:33 -07:00
|
|
|
def test__install_grub2_uefi_fstab(self, mock_get_part_uuid, mkdir_mock,
|
|
|
|
environ_mock, mock_md_get_raid_devices,
|
|
|
|
mock_is_md_device, mock_exists,
|
|
|
|
mock_execute, mock_dispatch):
|
|
|
|
mock_get_part_uuid.side_effect = [self.fake_root_part,
|
|
|
|
self.fake_efi_system_part]
|
|
|
|
environ_mock.get.return_value = '/sbin'
|
|
|
|
mock_is_md_device.return_value = False
|
|
|
|
mock_md_get_raid_devices.return_value = {}
|
|
|
|
mock_exists.side_effect = iter([False, True, False, True, True])
|
2021-02-12 14:47:16 +01:00
|
|
|
mock_execute.return_value = (hws.PARTUUID_DEVICE_TEMPLATE, '')
|
Create fstab entry with appropriate label
Depending on the how the stars align with partition images
being written to a remote system, we *may* end up with
*either* a Partition UUID value, or a Partition's UUID value.
Which are distinctly different.
This is becasue the value, when collected as a result of writing
an image to disk *falls* back and passes the value to enable
partition discovery and matching.
Later on, when we realized we ought to create an fstab entry,
we blindly re-used the value thinking it was, indeed, always
a Partition's UUID and not the Partition UUID. Obviously,
the label type is quite explicit, either UUID or PARTUUID
respectively, when initial ramdisk utilities such as dracut
are searching and mounting filesystems.
Adds capability to identify the correct label to utilize
based upon the current state of the block devices on disk.
Granted, we are likely only exposed to this because of IO
race conditions under high concurrecy load operations.
Normally this would only be seen on test VMs, but
systems being backed by a Storage Area Network *can*
exibit the same IO race conditions as virtual machines.
Change-Id: I953c936cbf8fad889108cbf4e50b1a15f511b38c
Resolves: rhbz#2058717
Story: #2009881
Task: 44623
2022-02-25 12:18:39 -08:00
|
|
|
|
2020-08-26 08:35:33 -07:00
|
|
|
with mock.patch('builtins.open', mock.mock_open()) as mock_open:
|
|
|
|
image._install_grub2(
|
|
|
|
self.fake_dev, root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
target_boot_mode='uefi')
|
|
|
|
write_calls = [
|
|
|
|
mock.call(self.fake_dir + '/etc/fstab', 'r+'),
|
|
|
|
mock.call().__enter__(),
|
|
|
|
mock.call().read(),
|
|
|
|
mock.call().writelines('UUID=%s\t/boot/efi\tvfat\t'
|
|
|
|
'umask=0077\t0\t1'
|
|
|
|
'\n' % self.fake_efi_system_part_uuid),
|
|
|
|
mock.call().__exit__(None, None, None)]
|
|
|
|
mock_open.assert_has_calls(write_calls)
|
|
|
|
|
|
|
|
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/dev'),
|
2020-08-26 08:35:33 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/dev',
|
|
|
|
self.fake_dir + '/dev'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/proc'),
|
2020-08-26 08:35:33 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/proc',
|
|
|
|
self.fake_dir + '/proc'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/run'),
|
2020-08-26 08:35:33 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/run',
|
|
|
|
self.fake_dir + '/run'),
|
|
|
|
mock.call('mount', '-t', 'sysfs', 'none',
|
|
|
|
self.fake_dir + '/sys'),
|
2021-06-11 18:20:49 +02:00
|
|
|
mock.call('mount', '/dev/fake2', self.fake_dir),
|
2020-08-26 08:35:33 -07:00
|
|
|
mock.call(('chroot %s /bin/sh -c "mount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
self.fake_dir + '/boot/efi'),
|
|
|
|
mock.call(('chroot %s /bin/sh -c "grub2-install"' %
|
|
|
|
self.fake_dir), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub2-install --removable"' %
|
|
|
|
self.fake_dir), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call(
|
|
|
|
'umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
'/tmp/fake-dir/boot/efi'),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub2-mkconfig -o '
|
|
|
|
'/boot/grub2/grub.cfg"' % self.fake_dir),
|
|
|
|
shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
|
|
|
use_standard_locale=True),
|
Create fstab entry with appropriate label
Depending on the how the stars align with partition images
being written to a remote system, we *may* end up with
*either* a Partition UUID value, or a Partition's UUID value.
Which are distinctly different.
This is becasue the value, when collected as a result of writing
an image to disk *falls* back and passes the value to enable
partition discovery and matching.
Later on, when we realized we ought to create an fstab entry,
we blindly re-used the value thinking it was, indeed, always
a Partition's UUID and not the Partition UUID. Obviously,
the label type is quite explicit, either UUID or PARTUUID
respectively, when initial ramdisk utilities such as dracut
are searching and mounting filesystems.
Adds capability to identify the correct label to utilize
based upon the current state of the block devices on disk.
Granted, we are likely only exposed to this because of IO
race conditions under high concurrecy load operations.
Normally this would only be seen on test VMs, but
systems being backed by a Storage Area Network *can*
exibit the same IO race conditions as virtual machines.
Change-Id: I953c936cbf8fad889108cbf4e50b1a15f511b38c
Resolves: rhbz#2058717
Story: #2009881
Task: 44623
2022-02-25 12:18:39 -08:00
|
|
|
mock.call('udevadm', 'settle'),
|
2021-02-12 14:47:16 +01:00
|
|
|
mock.call('lsblk', '-bia', '--json',
|
2022-08-16 11:11:16 +03:00
|
|
|
'-oKNAME,MODEL,SIZE,ROTA,'
|
|
|
|
+ 'TYPE,UUID,PARTUUID,SERIAL',
|
2021-02-12 14:47:16 +01:00
|
|
|
check_exit_code=[0]),
|
2020-08-26 08:35:33 -07:00
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call('umount', self.fake_dir + '/dev',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/proc',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/run',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/sys',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir, attempts=3,
|
|
|
|
delay_on_retry=True)]
|
|
|
|
mkdir_mock.assert_called_once_with(self.fake_dir + '/boot/efi')
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_root_uuid)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_efi_system_part_uuid)
|
|
|
|
self.assertFalse(mock_dispatch.called)
|
|
|
|
|
2022-04-07 15:15:17 -07:00
|
|
|
@mock.patch.object(hardware, 'get_multipath_status', lambda *_: False)
|
2020-08-26 08:35:33 -07:00
|
|
|
@mock.patch.object(image, '_efi_boot_setup', lambda *_: False)
|
2021-06-11 18:20:49 +02:00
|
|
|
@mock.patch.object(os.path, 'ismount', lambda *_: False)
|
2020-08-26 08:35:33 -07:00
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: True)
|
|
|
|
@mock.patch.object(os.path, 'exists', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
|
|
|
|
@mock.patch.object(os, 'environ', autospec=True)
|
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2020-08-26 08:35:33 -07:00
|
|
|
def test__install_grub2_uefi_no_fstab(
|
|
|
|
self, mock_get_part_uuid,
|
|
|
|
mkdir_mock,
|
|
|
|
environ_mock, mock_md_get_raid_devices,
|
|
|
|
mock_is_md_device, mock_exists,
|
|
|
|
mock_execute, mock_dispatch):
|
|
|
|
mock_get_part_uuid.side_effect = [self.fake_root_part,
|
|
|
|
self.fake_efi_system_part]
|
|
|
|
environ_mock.get.return_value = '/sbin'
|
|
|
|
mock_is_md_device.return_value = False
|
|
|
|
mock_md_get_raid_devices.return_value = {}
|
2021-02-12 14:47:16 +01:00
|
|
|
mock_execute.return_value = (hws.PARTUUID_DEVICE_TEMPLATE, '')
|
Create fstab entry with appropriate label
Depending on the how the stars align with partition images
being written to a remote system, we *may* end up with
*either* a Partition UUID value, or a Partition's UUID value.
Which are distinctly different.
This is becasue the value, when collected as a result of writing
an image to disk *falls* back and passes the value to enable
partition discovery and matching.
Later on, when we realized we ought to create an fstab entry,
we blindly re-used the value thinking it was, indeed, always
a Partition's UUID and not the Partition UUID. Obviously,
the label type is quite explicit, either UUID or PARTUUID
respectively, when initial ramdisk utilities such as dracut
are searching and mounting filesystems.
Adds capability to identify the correct label to utilize
based upon the current state of the block devices on disk.
Granted, we are likely only exposed to this because of IO
race conditions under high concurrecy load operations.
Normally this would only be seen on test VMs, but
systems being backed by a Storage Area Network *can*
exibit the same IO race conditions as virtual machines.
Change-Id: I953c936cbf8fad889108cbf4e50b1a15f511b38c
Resolves: rhbz#2058717
Story: #2009881
Task: 44623
2022-02-25 12:18:39 -08:00
|
|
|
# Validates the complete opposite path *and* no-write behavior
|
|
|
|
# occurs if the entry already exists.
|
2020-08-26 08:35:33 -07:00
|
|
|
fstab_data = (
|
Create fstab entry with appropriate label
Depending on the how the stars align with partition images
being written to a remote system, we *may* end up with
*either* a Partition UUID value, or a Partition's UUID value.
Which are distinctly different.
This is becasue the value, when collected as a result of writing
an image to disk *falls* back and passes the value to enable
partition discovery and matching.
Later on, when we realized we ought to create an fstab entry,
we blindly re-used the value thinking it was, indeed, always
a Partition's UUID and not the Partition UUID. Obviously,
the label type is quite explicit, either UUID or PARTUUID
respectively, when initial ramdisk utilities such as dracut
are searching and mounting filesystems.
Adds capability to identify the correct label to utilize
based upon the current state of the block devices on disk.
Granted, we are likely only exposed to this because of IO
race conditions under high concurrecy load operations.
Normally this would only be seen on test VMs, but
systems being backed by a Storage Area Network *can*
exibit the same IO race conditions as virtual machines.
Change-Id: I953c936cbf8fad889108cbf4e50b1a15f511b38c
Resolves: rhbz#2058717
Story: #2009881
Task: 44623
2022-02-25 12:18:39 -08:00
|
|
|
'PARTUUID=%s\tpath vfat option' % self.fake_efi_system_part_uuid)
|
2020-08-26 08:35:33 -07:00
|
|
|
mock_exists.side_effect = [True, False, True, True, True, False,
|
|
|
|
True, True]
|
|
|
|
with mock.patch('builtins.open',
|
|
|
|
mock.mock_open(read_data=fstab_data)) as mock_open:
|
|
|
|
image._install_grub2(
|
|
|
|
self.fake_dev, root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
target_boot_mode='uefi')
|
|
|
|
write_calls = [
|
|
|
|
mock.call(self.fake_dir + '/etc/fstab', 'r+'),
|
|
|
|
mock.call().__enter__(),
|
|
|
|
mock.call().read(),
|
|
|
|
mock.call().__exit__(None, None, None)]
|
|
|
|
mock_open.assert_has_calls(write_calls)
|
|
|
|
|
|
|
|
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/dev'),
|
2020-08-26 08:35:33 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/dev',
|
|
|
|
self.fake_dir + '/dev'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/proc'),
|
2020-08-26 08:35:33 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/proc',
|
|
|
|
self.fake_dir + '/proc'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/run'),
|
2020-08-26 08:35:33 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/run',
|
|
|
|
self.fake_dir + '/run'),
|
|
|
|
mock.call('mount', '-t', 'sysfs', 'none',
|
|
|
|
self.fake_dir + '/sys'),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub2-mkconfig -o '
|
|
|
|
'/boot/grub2/grub.cfg"' % self.fake_dir),
|
|
|
|
shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
|
|
|
use_standard_locale=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi'),
|
2021-06-11 18:20:49 +02:00
|
|
|
mock.call('mount', '/dev/fake2', self.fake_dir),
|
2020-08-26 08:35:33 -07:00
|
|
|
# NOTE(TheJulia): chroot mount is for whole disk images
|
|
|
|
mock.call(('chroot %s /bin/sh -c "mount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
self.fake_dir + '/boot/efi'),
|
|
|
|
mock.call(('chroot %s /bin/sh -c "grub2-install"' %
|
|
|
|
self.fake_dir), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub2-install --removable"' %
|
|
|
|
self.fake_dir), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call(
|
|
|
|
'umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
'/tmp/fake-dir/boot/efi'),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub2-mkconfig -o '
|
|
|
|
'/boot/grub2/grub.cfg"' % self.fake_dir),
|
|
|
|
shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
|
|
|
use_standard_locale=True),
|
Create fstab entry with appropriate label
Depending on the how the stars align with partition images
being written to a remote system, we *may* end up with
*either* a Partition UUID value, or a Partition's UUID value.
Which are distinctly different.
This is becasue the value, when collected as a result of writing
an image to disk *falls* back and passes the value to enable
partition discovery and matching.
Later on, when we realized we ought to create an fstab entry,
we blindly re-used the value thinking it was, indeed, always
a Partition's UUID and not the Partition UUID. Obviously,
the label type is quite explicit, either UUID or PARTUUID
respectively, when initial ramdisk utilities such as dracut
are searching and mounting filesystems.
Adds capability to identify the correct label to utilize
based upon the current state of the block devices on disk.
Granted, we are likely only exposed to this because of IO
race conditions under high concurrecy load operations.
Normally this would only be seen on test VMs, but
systems being backed by a Storage Area Network *can*
exibit the same IO race conditions as virtual machines.
Change-Id: I953c936cbf8fad889108cbf4e50b1a15f511b38c
Resolves: rhbz#2058717
Story: #2009881
Task: 44623
2022-02-25 12:18:39 -08:00
|
|
|
mock.call('udevadm', 'settle'),
|
2021-02-12 14:47:16 +01:00
|
|
|
mock.call('lsblk', '-bia', '--json',
|
2022-08-16 11:11:16 +03:00
|
|
|
'-oKNAME,MODEL,SIZE,ROTA,'
|
|
|
|
+ 'TYPE,UUID,PARTUUID,SERIAL',
|
2021-02-12 14:47:16 +01:00
|
|
|
check_exit_code=[0]),
|
2020-08-26 08:35:33 -07:00
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call('umount', self.fake_dir + '/dev',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/proc',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/run',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/sys',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir, attempts=3,
|
|
|
|
delay_on_retry=True)]
|
|
|
|
mkdir_mock.assert_called_once_with(self.fake_dir + '/boot/efi')
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_root_uuid)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_efi_system_part_uuid)
|
|
|
|
self.assertFalse(mock_dispatch.called)
|
2015-02-19 13:42:39 +00:00
|
|
|
|
2020-08-25 16:14:45 -07:00
|
|
|
@mock.patch.object(os.path, 'ismount', lambda *_: False)
|
|
|
|
@mock.patch.object(os, 'listdir', lambda *_: ['file1', 'file2'])
|
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
|
2020-08-26 08:35:33 -07:00
|
|
|
@mock.patch.object(image, '_append_uefi_to_fstab', autospec=True)
|
2020-08-25 16:14:45 -07:00
|
|
|
@mock.patch.object(image, '_efi_boot_setup', autospec=True)
|
|
|
|
@mock.patch.object(shutil, 'copytree', autospec=True)
|
|
|
|
@mock.patch.object(os.path, 'exists', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
|
|
|
|
@mock.patch.object(os, 'environ', autospec=True)
|
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2020-08-25 16:14:45 -07:00
|
|
|
def test__install_grub2_uefi_partition_image_with_loader(
|
|
|
|
self, mock_get_part_uuid, mkdir_mock,
|
|
|
|
environ_mock, mock_md_get_raid_devices,
|
|
|
|
mock_is_md_device, mock_exists,
|
|
|
|
mock_copytree, mock_efi_setup,
|
2020-08-26 08:35:33 -07:00
|
|
|
mock_append_to_fstab, mock_execute,
|
|
|
|
mock_dispatch):
|
|
|
|
mock_exists.side_effect = [True, False, True, True, True, False, True,
|
|
|
|
False, False]
|
2020-08-25 16:14:45 -07:00
|
|
|
mock_efi_setup.return_value = True
|
|
|
|
mock_get_part_uuid.side_effect = [self.fake_root_part,
|
|
|
|
self.fake_efi_system_part]
|
|
|
|
environ_mock.get.return_value = '/sbin'
|
|
|
|
mock_is_md_device.return_value = False
|
|
|
|
mock_md_get_raid_devices.return_value = {}
|
|
|
|
|
|
|
|
image._install_grub2(
|
|
|
|
self.fake_dev, root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
target_boot_mode='uefi')
|
|
|
|
mock_efi_setup.assert_called_once_with(self.fake_dev,
|
|
|
|
self.fake_efi_system_part_uuid)
|
|
|
|
mock_copytree.assert_has_calls([
|
|
|
|
mock.call(self.fake_dir + '/boot/efi/EFI',
|
|
|
|
self.fake_dir + '/efi_loader'),
|
|
|
|
mock.call(self.fake_dir + '/efi_loader',
|
|
|
|
self.fake_dir + '/boot/efi/EFI')])
|
|
|
|
|
|
|
|
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/dev'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/dev',
|
|
|
|
self.fake_dir + '/dev'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/proc'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/proc',
|
|
|
|
self.fake_dir + '/proc'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/run'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/run',
|
|
|
|
self.fake_dir + '/run'),
|
|
|
|
mock.call('mount', '-t', 'sysfs', 'none',
|
|
|
|
self.fake_dir + '/sys'),
|
|
|
|
mock.call('chroot %s /bin/sh -c "grub2-mkconfig -o '
|
|
|
|
'/boot/grub2/grub.cfg"' % self.fake_dir,
|
|
|
|
shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
|
|
|
use_standard_locale=True),
|
|
|
|
mock.call('mount', '-t', 'vfat', '/dev/fake1',
|
|
|
|
self.fake_dir + '/boot/efi'),
|
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi'),
|
|
|
|
mock.call('chroot %s /bin/sh -c "umount -a -t '
|
|
|
|
'vfat"' % self.fake_dir, shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call('umount', self.fake_dir + '/dev', attempts=3,
|
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/proc', attempts=3,
|
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/run', attempts=3,
|
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/sys', attempts=3,
|
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir, attempts=3,
|
|
|
|
delay_on_retry=True)]
|
|
|
|
mkdir_mock.assert_not_called()
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_root_uuid)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_efi_system_part_uuid)
|
|
|
|
self.assertFalse(mock_dispatch.called)
|
2020-08-26 08:35:33 -07:00
|
|
|
mock_append_to_fstab.assert_called_with(self.fake_dir,
|
|
|
|
self.fake_efi_system_part_uuid)
|
2020-08-25 16:14:45 -07:00
|
|
|
|
|
|
|
@mock.patch.object(os, 'listdir', lambda *_: ['file1', 'file2'])
|
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
|
Create fstab entry with appropriate label
Depending on the how the stars align with partition images
being written to a remote system, we *may* end up with
*either* a Partition UUID value, or a Partition's UUID value.
Which are distinctly different.
This is becasue the value, when collected as a result of writing
an image to disk *falls* back and passes the value to enable
partition discovery and matching.
Later on, when we realized we ought to create an fstab entry,
we blindly re-used the value thinking it was, indeed, always
a Partition's UUID and not the Partition UUID. Obviously,
the label type is quite explicit, either UUID or PARTUUID
respectively, when initial ramdisk utilities such as dracut
are searching and mounting filesystems.
Adds capability to identify the correct label to utilize
based upon the current state of the block devices on disk.
Granted, we are likely only exposed to this because of IO
race conditions under high concurrecy load operations.
Normally this would only be seen on test VMs, but
systems being backed by a Storage Area Network *can*
exibit the same IO race conditions as virtual machines.
Change-Id: I953c936cbf8fad889108cbf4e50b1a15f511b38c
Resolves: rhbz#2058717
Story: #2009881
Task: 44623
2022-02-25 12:18:39 -08:00
|
|
|
@mock.patch.object(image, '_append_uefi_to_fstab', autospec=True)
|
2020-08-25 16:14:45 -07:00
|
|
|
@mock.patch.object(shutil, 'copy2', autospec=True)
|
|
|
|
@mock.patch.object(os.path, 'isfile', autospec=True)
|
|
|
|
@mock.patch.object(image, '_efi_boot_setup', autospec=True)
|
|
|
|
@mock.patch.object(shutil, 'copytree', autospec=True)
|
|
|
|
@mock.patch.object(os.path, 'exists', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
|
|
|
|
@mock.patch.object(os, 'environ', autospec=True)
|
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2020-08-25 16:14:45 -07:00
|
|
|
def test__install_grub2_uefi_partition_image_with_loader_with_grubcfg(
|
|
|
|
self, mock_get_part_uuid, mkdir_mock,
|
|
|
|
environ_mock, mock_md_get_raid_devices,
|
|
|
|
mock_is_md_device, mock_exists,
|
|
|
|
mock_copytree, mock_efi_setup,
|
|
|
|
mock_isfile, mock_copy2,
|
Create fstab entry with appropriate label
Depending on the how the stars align with partition images
being written to a remote system, we *may* end up with
*either* a Partition UUID value, or a Partition's UUID value.
Which are distinctly different.
This is becasue the value, when collected as a result of writing
an image to disk *falls* back and passes the value to enable
partition discovery and matching.
Later on, when we realized we ought to create an fstab entry,
we blindly re-used the value thinking it was, indeed, always
a Partition's UUID and not the Partition UUID. Obviously,
the label type is quite explicit, either UUID or PARTUUID
respectively, when initial ramdisk utilities such as dracut
are searching and mounting filesystems.
Adds capability to identify the correct label to utilize
based upon the current state of the block devices on disk.
Granted, we are likely only exposed to this because of IO
race conditions under high concurrecy load operations.
Normally this would only be seen on test VMs, but
systems being backed by a Storage Area Network *can*
exibit the same IO race conditions as virtual machines.
Change-Id: I953c936cbf8fad889108cbf4e50b1a15f511b38c
Resolves: rhbz#2058717
Story: #2009881
Task: 44623
2022-02-25 12:18:39 -08:00
|
|
|
mock_fstab_append, mock_execute,
|
|
|
|
mock_dispatch):
|
2020-08-25 16:14:45 -07:00
|
|
|
mock_exists.return_value = True
|
|
|
|
mock_efi_setup.return_value = True
|
|
|
|
mock_get_part_uuid.side_effect = [self.fake_root_part,
|
|
|
|
self.fake_efi_system_part]
|
|
|
|
environ_mock.get.return_value = '/sbin'
|
|
|
|
mock_is_md_device.return_value = False
|
|
|
|
mock_md_get_raid_devices.return_value = {}
|
|
|
|
mock_isfile.side_effect = [True, False, False, True, True, False]
|
|
|
|
|
|
|
|
image._install_grub2(
|
|
|
|
self.fake_dev, root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
target_boot_mode='uefi')
|
|
|
|
mock_efi_setup.assert_called_once_with(self.fake_dev,
|
|
|
|
self.fake_efi_system_part_uuid)
|
|
|
|
mock_copytree.assert_has_calls([
|
|
|
|
mock.call(self.fake_dir + '/boot/efi/EFI',
|
|
|
|
self.fake_dir + '/efi_loader'),
|
|
|
|
mock.call(self.fake_dir + '/efi_loader',
|
|
|
|
self.fake_dir + '/boot/efi/EFI')])
|
|
|
|
|
|
|
|
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/dev'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/dev',
|
|
|
|
self.fake_dir + '/dev'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/proc'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/proc',
|
|
|
|
self.fake_dir + '/proc'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/run'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/run',
|
|
|
|
self.fake_dir + '/run'),
|
|
|
|
mock.call('mount', '-t', 'sysfs', 'none',
|
|
|
|
self.fake_dir + '/sys'),
|
|
|
|
mock.call(('chroot ' + self.fake_dir + ' /bin/sh -c '
|
|
|
|
'"grub2-mkconfig -o /boot/grub2/grub.cfg"'),
|
|
|
|
shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
|
|
|
use_standard_locale=True),
|
|
|
|
mock.call('mount', '-t', 'vfat', '/dev/fake1',
|
|
|
|
self.fake_dir + '/boot/efi'),
|
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi'),
|
|
|
|
mock.call(('chroot ' + self.fake_dir
|
|
|
|
+ ' /bin/sh -c "umount -a -t vfat"'),
|
|
|
|
shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call('umount', self.fake_dir + '/dev', attempts=3,
|
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/proc', attempts=3,
|
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/run', attempts=3,
|
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/sys', attempts=3,
|
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir, attempts=3,
|
|
|
|
delay_on_retry=True)]
|
|
|
|
mkdir_mock.assert_not_called()
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
mock_copy2.assert_has_calls([])
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_root_uuid)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_efi_system_part_uuid)
|
Create fstab entry with appropriate label
Depending on the how the stars align with partition images
being written to a remote system, we *may* end up with
*either* a Partition UUID value, or a Partition's UUID value.
Which are distinctly different.
This is becasue the value, when collected as a result of writing
an image to disk *falls* back and passes the value to enable
partition discovery and matching.
Later on, when we realized we ought to create an fstab entry,
we blindly re-used the value thinking it was, indeed, always
a Partition's UUID and not the Partition UUID. Obviously,
the label type is quite explicit, either UUID or PARTUUID
respectively, when initial ramdisk utilities such as dracut
are searching and mounting filesystems.
Adds capability to identify the correct label to utilize
based upon the current state of the block devices on disk.
Granted, we are likely only exposed to this because of IO
race conditions under high concurrecy load operations.
Normally this would only be seen on test VMs, but
systems being backed by a Storage Area Network *can*
exibit the same IO race conditions as virtual machines.
Change-Id: I953c936cbf8fad889108cbf4e50b1a15f511b38c
Resolves: rhbz#2058717
Story: #2009881
Task: 44623
2022-02-25 12:18:39 -08:00
|
|
|
mock_fstab_append.assert_called_once_with(
|
|
|
|
self.fake_dir,
|
|
|
|
self.fake_efi_system_part_uuid)
|
2020-08-25 16:14:45 -07:00
|
|
|
self.assertFalse(mock_dispatch.called)
|
|
|
|
|
2021-06-11 18:20:49 +02:00
|
|
|
@mock.patch.object(os.path, 'ismount', lambda *_: False)
|
2020-08-25 16:14:45 -07:00
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
|
2020-08-26 08:35:33 -07:00
|
|
|
@mock.patch.object(image, '_append_uefi_to_fstab', autospec=True)
|
2020-08-25 16:14:45 -07:00
|
|
|
@mock.patch.object(image, '_preserve_efi_assets', autospec=True)
|
|
|
|
@mock.patch.object(image, '_efi_boot_setup', autospec=True)
|
|
|
|
@mock.patch.object(os.path, 'exists', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
|
|
|
|
@mock.patch.object(os, 'environ', autospec=True)
|
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2020-08-25 16:14:45 -07:00
|
|
|
def test__install_grub2_uefi_partition_image_with_preserve_failure(
|
|
|
|
self, mock_get_part_uuid, mkdir_mock,
|
|
|
|
environ_mock, mock_md_get_raid_devices,
|
|
|
|
mock_is_md_device, mock_exists,
|
|
|
|
mock_efi_setup,
|
|
|
|
mock_preserve_efi_assets,
|
2020-08-26 08:35:33 -07:00
|
|
|
mock_append_to_fstab,
|
2020-08-25 16:14:45 -07:00
|
|
|
mock_execute, mock_dispatch):
|
|
|
|
mock_exists.return_value = True
|
|
|
|
mock_efi_setup.side_effect = Exception('meow')
|
|
|
|
mock_get_part_uuid.side_effect = [self.fake_root_part,
|
|
|
|
self.fake_efi_system_part]
|
|
|
|
environ_mock.get.return_value = '/sbin'
|
|
|
|
mock_is_md_device.return_value = False
|
|
|
|
mock_md_get_raid_devices.return_value = {}
|
|
|
|
mock_preserve_efi_assets.return_value = False
|
|
|
|
|
|
|
|
image._install_grub2(
|
|
|
|
self.fake_dev, root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
target_boot_mode='uefi')
|
|
|
|
self.assertFalse(mock_efi_setup.called)
|
|
|
|
|
2021-06-28 15:16:01 -07:00
|
|
|
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/dev'),
|
2021-06-28 15:16:01 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/dev',
|
|
|
|
self.fake_dir + '/dev'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/proc'),
|
2021-06-28 15:16:01 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/proc',
|
|
|
|
self.fake_dir + '/proc'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/run'),
|
2021-06-28 15:16:01 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/run',
|
|
|
|
self.fake_dir + '/run'),
|
|
|
|
mock.call('mount', '-t', 'sysfs', 'none',
|
|
|
|
self.fake_dir + '/sys'),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub2-mkconfig -o '
|
|
|
|
'/boot/grub2/grub.cfg"' % self.fake_dir),
|
|
|
|
shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
|
|
|
use_standard_locale=True),
|
|
|
|
mock.call('mount', '/dev/fake2', self.fake_dir),
|
|
|
|
mock.call(('chroot %s /bin/sh -c "mount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
self.fake_dir + '/boot/efi'),
|
|
|
|
mock.call(('chroot %s /bin/sh -c "grub2-install"' %
|
|
|
|
self.fake_dir), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub2-install --removable"' %
|
|
|
|
self.fake_dir), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call(
|
|
|
|
'umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
'/tmp/fake-dir/boot/efi'),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub2-mkconfig -o '
|
|
|
|
'/boot/grub2/grub.cfg"' % self.fake_dir),
|
|
|
|
shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
|
|
|
use_standard_locale=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call('umount', self.fake_dir + '/dev',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/proc',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/run',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/sys',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir, attempts=3,
|
|
|
|
delay_on_retry=True)]
|
|
|
|
|
|
|
|
mkdir_mock.assert_not_called()
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_root_uuid)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_efi_system_part_uuid)
|
|
|
|
self.assertFalse(mock_dispatch.called)
|
|
|
|
mock_preserve_efi_assets.assert_called_with(
|
|
|
|
self.fake_dir,
|
|
|
|
self.fake_dir + '/boot/efi/EFI',
|
|
|
|
'/dev/fake1',
|
|
|
|
self.fake_dir + '/boot/efi')
|
|
|
|
mock_append_to_fstab.assert_called_with(self.fake_dir,
|
|
|
|
self.fake_efi_system_part_uuid)
|
|
|
|
|
|
|
|
@mock.patch.object(os.path, 'ismount', lambda *_: False)
|
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
|
|
|
|
@mock.patch.object(image, '_append_uefi_to_fstab', autospec=True)
|
|
|
|
@mock.patch.object(image, '_preserve_efi_assets', autospec=True)
|
|
|
|
@mock.patch.object(image, '_efi_boot_setup', autospec=True)
|
|
|
|
@mock.patch.object(os.path, 'exists', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
|
|
|
|
@mock.patch.object(os, 'environ', autospec=True)
|
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2021-06-28 15:16:01 -07:00
|
|
|
def test__install_grub2_uefi_partition_image_with_preserve_failure2(
|
|
|
|
self, mock_get_part_uuid, mkdir_mock,
|
|
|
|
environ_mock, mock_md_get_raid_devices,
|
|
|
|
mock_is_md_device, mock_exists,
|
|
|
|
mock_efi_setup,
|
|
|
|
mock_preserve_efi_assets,
|
|
|
|
mock_append_to_fstab,
|
|
|
|
mock_execute, mock_dispatch):
|
|
|
|
mock_exists.return_value = True
|
|
|
|
mock_efi_setup.side_effect = Exception('meow')
|
|
|
|
mock_get_part_uuid.side_effect = [self.fake_root_part,
|
|
|
|
self.fake_efi_system_part]
|
|
|
|
environ_mock.get.return_value = '/sbin'
|
|
|
|
mock_is_md_device.return_value = False
|
|
|
|
mock_md_get_raid_devices.return_value = {}
|
|
|
|
mock_preserve_efi_assets.return_value = None
|
|
|
|
exec_results = [('', '')] * 21
|
|
|
|
already_exists = processutils.ProcessExecutionError(
|
|
|
|
'/dev is already mounted at /path')
|
|
|
|
# Mark mounts as already mounted, which is where os.path.ismount
|
|
|
|
# usage corresponds.
|
|
|
|
exec_results[6] = already_exists
|
|
|
|
exec_results[8] = already_exists
|
|
|
|
|
|
|
|
image._install_grub2(
|
|
|
|
self.fake_dev, root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
target_boot_mode='uefi')
|
|
|
|
self.assertFalse(mock_efi_setup.called)
|
|
|
|
|
2020-08-25 16:14:45 -07:00
|
|
|
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/dev'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/dev',
|
|
|
|
self.fake_dir + '/dev'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/proc'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/proc',
|
|
|
|
self.fake_dir + '/proc'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/run'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/run',
|
|
|
|
self.fake_dir + '/run'),
|
|
|
|
mock.call('mount', '-t', 'sysfs', 'none',
|
|
|
|
self.fake_dir + '/sys'),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub2-mkconfig -o '
|
|
|
|
'/boot/grub2/grub.cfg"' % self.fake_dir),
|
|
|
|
shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
|
|
|
use_standard_locale=True),
|
2021-06-11 18:20:49 +02:00
|
|
|
mock.call('mount', '/dev/fake2', self.fake_dir),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call(('chroot %s /bin/sh -c "mount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
self.fake_dir + '/boot/efi'),
|
|
|
|
mock.call(('chroot %s /bin/sh -c "grub2-install"' %
|
|
|
|
self.fake_dir), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub2-install --removable"' %
|
|
|
|
self.fake_dir), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call(
|
|
|
|
'umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
'/tmp/fake-dir/boot/efi'),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub2-mkconfig -o '
|
|
|
|
'/boot/grub2/grub.cfg"' % self.fake_dir),
|
|
|
|
shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
|
|
|
use_standard_locale=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call('umount', self.fake_dir + '/dev',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/proc',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/run',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/sys',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir, attempts=3,
|
|
|
|
delay_on_retry=True)]
|
|
|
|
|
|
|
|
mkdir_mock.assert_not_called()
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_root_uuid)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_efi_system_part_uuid)
|
|
|
|
self.assertFalse(mock_dispatch.called)
|
|
|
|
mock_preserve_efi_assets.assert_called_with(
|
|
|
|
self.fake_dir,
|
|
|
|
self.fake_dir + '/boot/efi/EFI',
|
2021-04-14 08:50:16 +02:00
|
|
|
'/dev/fake1',
|
2020-08-25 16:14:45 -07:00
|
|
|
self.fake_dir + '/boot/efi')
|
2020-08-26 08:35:33 -07:00
|
|
|
mock_append_to_fstab.assert_called_with(self.fake_dir,
|
|
|
|
self.fake_efi_system_part_uuid)
|
2020-08-25 16:14:45 -07:00
|
|
|
|
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
|
Create fstab entry with appropriate label
Depending on the how the stars align with partition images
being written to a remote system, we *may* end up with
*either* a Partition UUID value, or a Partition's UUID value.
Which are distinctly different.
This is becasue the value, when collected as a result of writing
an image to disk *falls* back and passes the value to enable
partition discovery and matching.
Later on, when we realized we ought to create an fstab entry,
we blindly re-used the value thinking it was, indeed, always
a Partition's UUID and not the Partition UUID. Obviously,
the label type is quite explicit, either UUID or PARTUUID
respectively, when initial ramdisk utilities such as dracut
are searching and mounting filesystems.
Adds capability to identify the correct label to utilize
based upon the current state of the block devices on disk.
Granted, we are likely only exposed to this because of IO
race conditions under high concurrecy load operations.
Normally this would only be seen on test VMs, but
systems being backed by a Storage Area Network *can*
exibit the same IO race conditions as virtual machines.
Change-Id: I953c936cbf8fad889108cbf4e50b1a15f511b38c
Resolves: rhbz#2058717
Story: #2009881
Task: 44623
2022-02-25 12:18:39 -08:00
|
|
|
@mock.patch.object(image, '_append_uefi_to_fstab', autospec=True)
|
2020-08-25 16:14:45 -07:00
|
|
|
@mock.patch.object(os, 'listdir', autospec=True)
|
|
|
|
@mock.patch.object(shutil, 'copy2', autospec=True)
|
|
|
|
@mock.patch.object(os.path, 'isfile', autospec=True)
|
|
|
|
@mock.patch.object(image, '_efi_boot_setup', autospec=True)
|
|
|
|
@mock.patch.object(shutil, 'copytree', autospec=True)
|
|
|
|
@mock.patch.object(os.path, 'exists', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
|
|
|
|
@mock.patch.object(os, 'environ', autospec=True)
|
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2020-08-25 16:14:45 -07:00
|
|
|
def test__install_grub2_uefi_partition_image_with_loader_grubcfg_fails(
|
|
|
|
self, mock_get_part_uuid, mkdir_mock,
|
|
|
|
environ_mock, mock_md_get_raid_devices,
|
|
|
|
mock_is_md_device, mock_exists,
|
|
|
|
mock_copytree, mock_efi_setup,
|
|
|
|
mock_isfile, mock_copy2,
|
Create fstab entry with appropriate label
Depending on the how the stars align with partition images
being written to a remote system, we *may* end up with
*either* a Partition UUID value, or a Partition's UUID value.
Which are distinctly different.
This is becasue the value, when collected as a result of writing
an image to disk *falls* back and passes the value to enable
partition discovery and matching.
Later on, when we realized we ought to create an fstab entry,
we blindly re-used the value thinking it was, indeed, always
a Partition's UUID and not the Partition UUID. Obviously,
the label type is quite explicit, either UUID or PARTUUID
respectively, when initial ramdisk utilities such as dracut
are searching and mounting filesystems.
Adds capability to identify the correct label to utilize
based upon the current state of the block devices on disk.
Granted, we are likely only exposed to this because of IO
race conditions under high concurrecy load operations.
Normally this would only be seen on test VMs, but
systems being backed by a Storage Area Network *can*
exibit the same IO race conditions as virtual machines.
Change-Id: I953c936cbf8fad889108cbf4e50b1a15f511b38c
Resolves: rhbz#2058717
Story: #2009881
Task: 44623
2022-02-25 12:18:39 -08:00
|
|
|
mock_oslistdir, mock_append_to_fstab,
|
|
|
|
mock_execute, mock_dispatch):
|
2020-08-25 16:14:45 -07:00
|
|
|
mock_exists.return_value = True
|
|
|
|
mock_efi_setup.return_value = True
|
|
|
|
mock_get_part_uuid.side_effect = [self.fake_root_part,
|
|
|
|
self.fake_efi_system_part]
|
|
|
|
environ_mock.get.return_value = '/sbin'
|
|
|
|
mock_is_md_device.return_value = False
|
|
|
|
mock_md_get_raid_devices.return_value = {}
|
|
|
|
mock_isfile.side_effect = [True, False, False, True, False,
|
|
|
|
True, False]
|
|
|
|
mock_copy2.side_effect = OSError('copy failed')
|
|
|
|
mock_oslistdir.return_value = ['file1', 'file2']
|
|
|
|
|
|
|
|
image._install_grub2(
|
|
|
|
self.fake_dev, root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
target_boot_mode='uefi')
|
|
|
|
mock_efi_setup.assert_called_once_with(self.fake_dev,
|
|
|
|
self.fake_efi_system_part_uuid)
|
|
|
|
mock_copytree.assert_has_calls([
|
|
|
|
mock.call(self.fake_dir + '/boot/efi/EFI',
|
|
|
|
self.fake_dir + '/efi_loader'),
|
|
|
|
mock.call(self.fake_dir + '/efi_loader',
|
|
|
|
self.fake_dir + '/boot/efi/EFI')])
|
|
|
|
|
|
|
|
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/dev'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/dev',
|
|
|
|
self.fake_dir + '/dev'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/proc'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/proc',
|
|
|
|
self.fake_dir + '/proc'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/run'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/run',
|
|
|
|
self.fake_dir + '/run'),
|
|
|
|
mock.call('mount', '-t', 'sysfs', 'none',
|
|
|
|
self.fake_dir + '/sys'),
|
|
|
|
mock.call(('chroot ' + self.fake_dir + ' /bin/sh -c '
|
|
|
|
'"grub2-mkconfig -o /boot/grub2/grub.cfg"'),
|
|
|
|
shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
|
|
|
use_standard_locale=True),
|
|
|
|
mock.call('mount', '-t', 'vfat', '/dev/fake1',
|
|
|
|
self.fake_dir + '/boot/efi'),
|
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi'),
|
|
|
|
mock.call(('chroot ' + self.fake_dir
|
|
|
|
+ ' /bin/sh -c "umount -a -t vfat"'),
|
|
|
|
shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call('umount', self.fake_dir + '/dev', attempts=3,
|
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/proc', attempts=3,
|
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/run', attempts=3,
|
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/sys', attempts=3,
|
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir, attempts=3,
|
|
|
|
delay_on_retry=True)]
|
|
|
|
mkdir_mock.assert_not_called()
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
self.assertEqual(3, mock_copy2.call_count)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_root_uuid)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_efi_system_part_uuid)
|
|
|
|
self.assertFalse(mock_dispatch.called)
|
|
|
|
self.assertEqual(2, mock_oslistdir.call_count)
|
Create fstab entry with appropriate label
Depending on the how the stars align with partition images
being written to a remote system, we *may* end up with
*either* a Partition UUID value, or a Partition's UUID value.
Which are distinctly different.
This is becasue the value, when collected as a result of writing
an image to disk *falls* back and passes the value to enable
partition discovery and matching.
Later on, when we realized we ought to create an fstab entry,
we blindly re-used the value thinking it was, indeed, always
a Partition's UUID and not the Partition UUID. Obviously,
the label type is quite explicit, either UUID or PARTUUID
respectively, when initial ramdisk utilities such as dracut
are searching and mounting filesystems.
Adds capability to identify the correct label to utilize
based upon the current state of the block devices on disk.
Granted, we are likely only exposed to this because of IO
race conditions under high concurrecy load operations.
Normally this would only be seen on test VMs, but
systems being backed by a Storage Area Network *can*
exibit the same IO race conditions as virtual machines.
Change-Id: I953c936cbf8fad889108cbf4e50b1a15f511b38c
Resolves: rhbz#2058717
Story: #2009881
Task: 44623
2022-02-25 12:18:39 -08:00
|
|
|
mock_append_to_fstab.assert_called_with(self.fake_dir,
|
|
|
|
self.fake_efi_system_part_uuid)
|
2020-08-25 16:14:45 -07:00
|
|
|
|
2021-06-11 18:20:49 +02:00
|
|
|
@mock.patch.object(os.path, 'ismount', lambda *_: False)
|
2020-08-25 16:14:45 -07:00
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
|
|
|
|
@mock.patch.object(os, 'listdir', autospec=True)
|
2020-08-26 08:35:33 -07:00
|
|
|
@mock.patch.object(image, '_append_uefi_to_fstab', autospec=True)
|
2020-08-25 16:14:45 -07:00
|
|
|
@mock.patch.object(image, '_efi_boot_setup', autospec=True)
|
|
|
|
@mock.patch.object(shutil, 'copytree', autospec=True)
|
|
|
|
@mock.patch.object(os.path, 'exists', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
|
|
|
|
@mock.patch.object(os, 'environ', autospec=True)
|
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2020-08-25 16:14:45 -07:00
|
|
|
def test__install_grub2_uefi_partition_image_with_no_loader(
|
|
|
|
self, mock_get_part_uuid, mkdir_mock,
|
|
|
|
environ_mock, mock_md_get_raid_devices,
|
|
|
|
mock_is_md_device, mock_exists,
|
|
|
|
mock_copytree, mock_efi_setup,
|
2020-08-26 08:35:33 -07:00
|
|
|
mock_append_to_fstab, mock_oslistdir,
|
|
|
|
mock_execute, mock_dispatch):
|
2020-08-25 16:14:45 -07:00
|
|
|
mock_exists.side_effect = [True, False, False, True, True, True, True]
|
|
|
|
mock_efi_setup.side_effect = Exception('meow')
|
|
|
|
mock_oslistdir.return_value = ['file1']
|
|
|
|
mock_get_part_uuid.side_effect = [self.fake_root_part,
|
|
|
|
self.fake_efi_system_part]
|
|
|
|
environ_mock.get.return_value = '/sbin'
|
|
|
|
mock_is_md_device.return_value = False
|
|
|
|
mock_md_get_raid_devices.return_value = {}
|
|
|
|
|
|
|
|
image._install_grub2(
|
|
|
|
self.fake_dev, root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
target_boot_mode='uefi')
|
|
|
|
|
|
|
|
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/dev'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/dev',
|
|
|
|
self.fake_dir + '/dev'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/proc'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/proc',
|
|
|
|
self.fake_dir + '/proc'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/run'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '-o', 'bind', '/run',
|
|
|
|
self.fake_dir + '/run'),
|
|
|
|
mock.call('mount', '-t', 'sysfs', 'none',
|
|
|
|
self.fake_dir + '/sys'),
|
|
|
|
mock.call('mount', '-t', 'vfat', '/dev/fake1',
|
|
|
|
self.fake_dir + '/boot/efi'),
|
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi'),
|
2021-06-11 18:20:49 +02:00
|
|
|
mock.call('mount', '/dev/fake2', self.fake_dir),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call(('chroot %s /bin/sh -c "mount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
self.fake_dir + '/boot/efi'),
|
|
|
|
mock.call(('chroot %s /bin/sh -c "grub2-install"' %
|
|
|
|
self.fake_dir), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub2-install --removable"' %
|
|
|
|
self.fake_dir), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call(
|
|
|
|
'umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
'/tmp/fake-dir/boot/efi'),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub2-mkconfig -o '
|
|
|
|
'/boot/grub2/grub.cfg"' % self.fake_dir),
|
|
|
|
shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
|
|
|
use_standard_locale=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call('umount', self.fake_dir + '/dev',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/proc',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/run',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/sys',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir, attempts=3,
|
|
|
|
delay_on_retry=True)]
|
|
|
|
|
|
|
|
mkdir_mock.assert_not_called()
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
self.assertEqual(2, mock_copytree.call_count)
|
|
|
|
self.assertTrue(mock_efi_setup.called)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_root_uuid)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_efi_system_part_uuid)
|
|
|
|
self.assertFalse(mock_dispatch.called)
|
2020-08-26 08:35:33 -07:00
|
|
|
mock_append_to_fstab.assert_called_with(self.fake_dir,
|
|
|
|
self.fake_efi_system_part_uuid)
|
2020-08-25 16:14:45 -07:00
|
|
|
|
2019-08-29 16:22:50 -04:00
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
|
2019-02-26 17:56:20 +01:00
|
|
|
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
2019-10-17 11:14:04 +00:00
|
|
|
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(os, 'environ', autospec=True)
|
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2015-03-12 09:15:49 +00:00
|
|
|
def test__install_grub2_uefi_umount_fails(
|
2019-02-26 17:56:20 +01:00
|
|
|
self, mock_get_part_uuid, mkdir_mock, environ_mock,
|
2019-10-17 11:14:04 +00:00
|
|
|
mock_md_get_raid_devices, mock_is_md_device, mock_execute,
|
|
|
|
mock_dispatch):
|
2015-03-12 09:15:49 +00:00
|
|
|
mock_get_part_uuid.side_effect = [self.fake_root_part,
|
|
|
|
self.fake_efi_system_part]
|
2019-02-26 17:56:20 +01:00
|
|
|
mock_is_md_device.return_value = False
|
2019-10-17 11:14:04 +00:00
|
|
|
mock_md_get_raid_devices.return_value = {}
|
2015-03-12 09:15:49 +00:00
|
|
|
|
|
|
|
def umount_raise_func(*args, **kwargs):
|
|
|
|
if args[0] == 'umount':
|
|
|
|
raise processutils.ProcessExecutionError('error')
|
|
|
|
|
|
|
|
mock_execute.side_effect = umount_raise_func
|
|
|
|
environ_mock.get.return_value = '/sbin'
|
|
|
|
self.assertRaises(errors.CommandExecutionError,
|
|
|
|
image._install_grub2,
|
|
|
|
self.fake_dev, root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid)
|
|
|
|
|
|
|
|
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/dev'),
|
2015-03-12 09:15:49 +00:00
|
|
|
mock.call('mount', '-o', 'bind', '/dev',
|
|
|
|
self.fake_dir + '/dev'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/proc'),
|
2015-03-12 09:15:49 +00:00
|
|
|
mock.call('mount', '-o', 'bind', '/proc',
|
|
|
|
self.fake_dir + '/proc'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/run'),
|
2019-04-24 23:25:19 +01:00
|
|
|
mock.call('mount', '-o', 'bind', '/run',
|
|
|
|
self.fake_dir + '/run'),
|
2015-10-06 14:50:55 -04:00
|
|
|
mock.call('mount', '-t', 'sysfs', 'none',
|
|
|
|
self.fake_dir + '/sys'),
|
2020-08-25 16:14:45 -07:00
|
|
|
mock.call('mount', '/dev/fake2', self.fake_dir),
|
2020-05-05 16:45:51 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c "mount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2015-03-12 09:15:49 +00:00
|
|
|
mock.call('mount', self.fake_efi_system_part,
|
|
|
|
self.fake_dir + '/boot/efi'),
|
2019-08-06 13:52:13 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c "grub-install"' %
|
|
|
|
self.fake_dir), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2017-01-16 21:32:37 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
2019-08-06 13:52:13 +02:00
|
|
|
'"grub-install --removable"' % self.fake_dir),
|
2015-03-12 09:15:49 +00:00
|
|
|
shell=True,
|
2019-08-06 13:52:13 +02:00
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
# Call from for loop
|
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
# Call from finally
|
2015-03-12 09:15:49 +00:00
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi',
|
2019-08-06 13:52:13 +02:00
|
|
|
attempts=3, delay_on_retry=True)
|
|
|
|
]
|
2015-03-12 09:15:49 +00:00
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
|
2019-08-29 16:22:50 -04:00
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
|
2019-02-26 17:56:20 +01:00
|
|
|
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
2019-10-17 11:14:04 +00:00
|
|
|
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
|
2017-11-17 16:34:24 +01:00
|
|
|
@mock.patch.object(os, 'environ', autospec=True)
|
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2017-11-17 16:34:24 +01:00
|
|
|
def test__install_grub2_uefi_mount_fails(
|
2019-02-26 17:56:20 +01:00
|
|
|
self, mock_get_part_uuid, mkdir_mock, environ_mock,
|
2019-10-17 11:14:04 +00:00
|
|
|
mock_is_md_device, mock_md_get_raid_devices, mock_execute,
|
|
|
|
mock_dispatch):
|
2017-11-17 16:34:24 +01:00
|
|
|
mock_get_part_uuid.side_effect = [self.fake_root_part,
|
|
|
|
self.fake_efi_system_part]
|
2019-10-17 11:14:04 +00:00
|
|
|
mock_is_md_device.side_effect = [False, False]
|
2020-05-05 16:45:51 +02:00
|
|
|
environ_mock.get.return_value = '/sbin'
|
2019-10-17 11:14:04 +00:00
|
|
|
mock_md_get_raid_devices.return_value = {}
|
2017-11-17 16:34:24 +01:00
|
|
|
|
|
|
|
def mount_raise_func(*args, **kwargs):
|
|
|
|
if args[0] == 'mount':
|
|
|
|
raise processutils.ProcessExecutionError('error')
|
|
|
|
|
|
|
|
mock_execute.side_effect = mount_raise_func
|
|
|
|
self.assertRaises(errors.CommandExecutionError,
|
|
|
|
image._install_grub2,
|
|
|
|
self.fake_dev, root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid)
|
|
|
|
|
|
|
|
expected = [mock.call('mount', '/dev/fake2', self.fake_dir),
|
2020-05-05 16:45:51 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2017-11-17 16:34:24 +01:00
|
|
|
mock.call('umount', self.fake_dir + '/dev',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/proc',
|
|
|
|
attempts=3, delay_on_retry=True),
|
2019-04-24 23:25:19 +01:00
|
|
|
mock.call('umount', self.fake_dir + '/run',
|
|
|
|
attempts=3, delay_on_retry=True),
|
2017-11-17 16:34:24 +01:00
|
|
|
mock.call('umount', self.fake_dir + '/sys',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir, attempts=3,
|
|
|
|
delay_on_retry=True)]
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
|
2019-08-29 16:22:50 -04:00
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: False)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2015-03-12 09:15:49 +00:00
|
|
|
def test__install_grub2_command_fail(self, mock_get_part_uuid,
|
|
|
|
mock_execute,
|
2015-02-19 13:42:39 +00:00
|
|
|
mock_dispatch):
|
2015-03-12 09:15:49 +00:00
|
|
|
mock_get_part_uuid.return_value = self.fake_root_part
|
2015-02-19 13:42:39 +00:00
|
|
|
mock_execute.side_effect = processutils.ProcessExecutionError('boom')
|
|
|
|
|
|
|
|
self.assertRaises(errors.CommandExecutionError, image._install_grub2,
|
|
|
|
self.fake_dev, self.fake_root_uuid)
|
|
|
|
|
2015-03-12 09:15:49 +00:00
|
|
|
mock_get_part_uuid.assert_called_once_with(self.fake_dev,
|
|
|
|
uuid=self.fake_root_uuid)
|
2015-02-19 13:42:39 +00:00
|
|
|
self.assertFalse(mock_dispatch.called)
|
|
|
|
|
2019-08-06 13:52:13 +02:00
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: True)
|
|
|
|
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'md_restart', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'get_holder_disks', autospec=True,
|
|
|
|
return_value=['/dev/sda', '/dev/sdb'])
|
|
|
|
@mock.patch.object(os, 'environ', autospec=True)
|
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2022-01-28 08:38:28 +01:00
|
|
|
@mock.patch.object(raid_utils, 'prepare_boot_partitions_for_softraid',
|
2019-08-06 13:52:13 +02:00
|
|
|
autospec=True,
|
2021-04-14 08:50:16 +02:00
|
|
|
return_value='/dev/md/esp')
|
2019-08-06 13:52:13 +02:00
|
|
|
@mock.patch.object(image, '_has_dracut',
|
|
|
|
autospec=True,
|
|
|
|
return_value=False)
|
|
|
|
def test__install_grub2_softraid_uefi_gpt(
|
|
|
|
self, mock_dracut,
|
|
|
|
mock_prepare, mock_get_part_uuid, mkdir_mock, environ_mock,
|
|
|
|
mock_holder, mock_md_get_raid_devices, mock_restart,
|
|
|
|
mock_is_md_device,
|
|
|
|
mock_execute, mock_dispatch):
|
|
|
|
|
2021-06-03 13:16:55 +12:00
|
|
|
# return success for every execute call
|
2022-09-13 16:53:07 +09:00
|
|
|
mock_execute.side_effect = [('', '')] * 24
|
2021-06-03 13:16:55 +12:00
|
|
|
|
|
|
|
# make grub2-install calls fail
|
|
|
|
grub_failure = processutils.ProcessExecutionError(
|
|
|
|
stdout='',
|
|
|
|
stderr='grub2-install: error: this utility cannot be used '
|
|
|
|
'for EFI platforms because it does not support '
|
|
|
|
'UEFI Secure Boot.\n',
|
|
|
|
exit_code=1,
|
|
|
|
cmd='grub2-install'
|
|
|
|
)
|
2022-09-13 16:53:07 +09:00
|
|
|
mock_execute.side_effect[12] = grub_failure
|
|
|
|
mock_execute.side_effect[13] = grub_failure
|
2021-06-03 13:16:55 +12:00
|
|
|
|
2019-08-06 13:52:13 +02:00
|
|
|
mock_get_part_uuid.side_effect = [self.fake_root_part,
|
|
|
|
self.fake_efi_system_part]
|
|
|
|
environ_mock.get.return_value = '/sbin'
|
|
|
|
mock_is_md_device.return_value = True
|
|
|
|
mock_md_get_raid_devices.return_value = {}
|
|
|
|
|
|
|
|
image._install_grub2(
|
|
|
|
self.fake_dev, root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=self.fake_efi_system_part_uuid,
|
|
|
|
target_boot_mode='uefi')
|
|
|
|
|
2022-02-14 11:50:49 +01:00
|
|
|
expected = [mock.call('partx', '-av', '/dev/fake', attempts=3,
|
2021-06-03 13:16:55 +12:00
|
|
|
delay_on_retry=True),
|
|
|
|
mock.call('udevadm', 'settle'),
|
|
|
|
mock.call('mount', '/dev/fake2', self.fake_dir),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/dev'),
|
2019-08-06 13:52:13 +02:00
|
|
|
mock.call('mount', '-o', 'bind', '/dev',
|
|
|
|
self.fake_dir + '/dev'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/proc'),
|
2019-08-06 13:52:13 +02:00
|
|
|
mock.call('mount', '-o', 'bind', '/proc',
|
|
|
|
self.fake_dir + '/proc'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/run'),
|
2019-08-06 13:52:13 +02:00
|
|
|
mock.call('mount', '-o', 'bind', '/run',
|
|
|
|
self.fake_dir + '/run'),
|
|
|
|
mock.call('mount', '-t', 'sysfs', 'none',
|
|
|
|
self.fake_dir + '/sys'),
|
2020-05-05 16:45:51 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c "mount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2021-04-14 08:50:16 +02:00
|
|
|
mock.call('mount', '/dev/md/esp',
|
2019-08-06 13:52:13 +02:00
|
|
|
self.fake_dir + '/boot/efi'),
|
|
|
|
mock.call(('chroot %s /bin/sh -c "grub-install"' %
|
|
|
|
self.fake_dir), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub-install --removable"' %
|
|
|
|
self.fake_dir), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call(
|
|
|
|
'umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
2021-04-14 08:50:16 +02:00
|
|
|
mock.call('mount', '/dev/md/esp',
|
2019-08-06 13:52:13 +02:00
|
|
|
'/tmp/fake-dir/boot/efi'),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub-mkconfig -o '
|
|
|
|
'/boot/grub/grub.cfg"' % self.fake_dir),
|
|
|
|
shell=True,
|
|
|
|
env_variables={
|
2020-09-16 13:10:13 -07:00
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
2020-08-25 16:14:45 -07:00
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
2020-09-16 13:10:13 -07:00
|
|
|
use_standard_locale=True),
|
2019-08-06 13:52:13 +02:00
|
|
|
mock.call('umount', self.fake_dir + '/boot/efi',
|
|
|
|
attempts=3, delay_on_retry=True),
|
2020-05-05 16:45:51 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2019-08-06 13:52:13 +02:00
|
|
|
mock.call('umount', self.fake_dir + '/dev',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/proc',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/run',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/sys',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir, attempts=3,
|
|
|
|
delay_on_retry=True)]
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_root_uuid)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_efi_system_part_uuid)
|
|
|
|
self.assertFalse(mock_dispatch.called)
|
|
|
|
mock_prepare.assert_called_once_with(self.fake_dev,
|
|
|
|
['/dev/sda', '/dev/sdb'],
|
|
|
|
self.fake_efi_system_part, 'uefi')
|
|
|
|
mock_restart.assert_called_once_with(self.fake_dev)
|
|
|
|
mock_holder.assert_called_once_with(self.fake_dev)
|
|
|
|
mock_dracut.assert_called_once_with(self.fake_dir)
|
|
|
|
|
|
|
|
@mock.patch.object(image, '_is_bootloader_loaded', lambda *_: True)
|
|
|
|
@mock.patch.object(hardware, 'is_md_device', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'md_restart', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'md_get_raid_devices', autospec=True)
|
|
|
|
@mock.patch.object(hardware, 'get_holder_disks', autospec=True,
|
|
|
|
return_value=['/dev/sda', '/dev/sdb'])
|
|
|
|
@mock.patch.object(os, 'environ', autospec=True)
|
|
|
|
@mock.patch.object(os, 'makedirs', autospec=True)
|
2021-10-27 13:45:10 +02:00
|
|
|
@mock.patch.object(partition_utils, 'get_partition', autospec=True)
|
2022-01-28 08:38:28 +01:00
|
|
|
@mock.patch.object(raid_utils, 'prepare_boot_partitions_for_softraid',
|
2019-08-06 13:52:13 +02:00
|
|
|
autospec=True,
|
|
|
|
return_value=[])
|
|
|
|
@mock.patch.object(image, '_has_dracut',
|
|
|
|
autospec=True,
|
|
|
|
return_value=False)
|
|
|
|
def test__install_grub2_softraid_bios(
|
|
|
|
self, mock_dracut,
|
|
|
|
mock_prepare, mock_get_part_uuid, mkdir_mock, environ_mock,
|
|
|
|
mock_holder, mock_md_get_raid_devices, mock_restart,
|
|
|
|
mock_is_md_device,
|
|
|
|
mock_execute, mock_dispatch):
|
|
|
|
|
|
|
|
mock_get_part_uuid.side_effect = [self.fake_root_part,
|
|
|
|
self.fake_efi_system_part]
|
|
|
|
environ_mock.get.return_value = '/sbin'
|
|
|
|
mock_is_md_device.return_value = True
|
|
|
|
mock_md_get_raid_devices.return_value = {}
|
|
|
|
|
|
|
|
image._install_grub2(
|
|
|
|
self.fake_dev, root_uuid=self.fake_root_uuid,
|
|
|
|
efi_system_part_uuid=None,
|
|
|
|
target_boot_mode='bios')
|
|
|
|
|
|
|
|
expected = [
|
|
|
|
mock.call('mount', '/dev/fake2', self.fake_dir),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/dev'),
|
2019-08-06 13:52:13 +02:00
|
|
|
mock.call('mount', '-o', 'bind', '/dev',
|
|
|
|
self.fake_dir + '/dev'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/proc'),
|
2019-08-06 13:52:13 +02:00
|
|
|
mock.call('mount', '-o', 'bind', '/proc',
|
|
|
|
self.fake_dir + '/proc'),
|
2022-09-13 16:53:07 +09:00
|
|
|
mock.call('mkdir', '-p', self.fake_dir + '/run'),
|
2019-08-06 13:52:13 +02:00
|
|
|
mock.call('mount', '-o', 'bind', '/run',
|
|
|
|
self.fake_dir + '/run'),
|
|
|
|
mock.call('mount', '-t', 'sysfs', 'none',
|
|
|
|
self.fake_dir + '/sys'),
|
2020-05-05 16:45:51 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c "mount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2019-08-06 13:52:13 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub-install %s"' %
|
|
|
|
(self.fake_dir, '/dev/sda')), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub-install %s"' %
|
|
|
|
(self.fake_dir, '/dev/sdb')), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
|
|
|
mock.call(('chroot %s /bin/sh -c '
|
|
|
|
'"grub-mkconfig -o '
|
|
|
|
'/boot/grub/grub.cfg"' % self.fake_dir),
|
|
|
|
shell=True,
|
|
|
|
env_variables={
|
2020-09-16 13:10:13 -07:00
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin',
|
2020-08-25 16:14:45 -07:00
|
|
|
'GRUB_DISABLE_OS_PROBER': 'true',
|
|
|
|
'GRUB_SAVEDEFAULT': 'true'},
|
2020-09-16 13:10:13 -07:00
|
|
|
use_standard_locale=True),
|
2020-05-05 16:45:51 +02:00
|
|
|
mock.call(('chroot %s /bin/sh -c "umount -a -t vfat"' %
|
|
|
|
(self.fake_dir)), shell=True,
|
|
|
|
env_variables={
|
|
|
|
'PATH': '/sbin:/bin:/usr/sbin:/sbin'}),
|
2019-08-06 13:52:13 +02:00
|
|
|
mock.call('umount', self.fake_dir + '/dev',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/proc',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/run',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir + '/sys',
|
|
|
|
attempts=3, delay_on_retry=True),
|
|
|
|
mock.call('umount', self.fake_dir, attempts=3,
|
|
|
|
delay_on_retry=True)]
|
|
|
|
self.assertFalse(mkdir_mock.called)
|
|
|
|
mock_execute.assert_has_calls(expected)
|
|
|
|
mock_get_part_uuid.assert_any_call(self.fake_dev,
|
|
|
|
uuid=self.fake_root_uuid)
|
|
|
|
self.assertFalse(mock_dispatch.called)
|
|
|
|
mock_prepare.assert_called_once_with(self.fake_dev,
|
|
|
|
['/dev/sda', '/dev/sdb'],
|
|
|
|
None, 'bios')
|
|
|
|
mock_restart.assert_called_once_with(self.fake_dev)
|
|
|
|
mock_holder.assert_called_once_with(self.fake_dev)
|
|
|
|
mock_dracut.assert_called_once_with(self.fake_dir)
|
|
|
|
|
2019-08-29 16:22:50 -04:00
|
|
|
def test__is_bootloader_loaded(self, mock_execute,
|
|
|
|
mock_dispatch):
|
2020-03-23 07:46:48 -07:00
|
|
|
mock_dispatch.return_value = hardware.BootInfo(
|
|
|
|
current_boot_mode='bios')
|
2019-08-29 16:22:50 -04:00
|
|
|
parted_output = ('BYT;\n'
|
|
|
|
'/dev/loop1:46.1MB:loopback:512:512:gpt:Loopback '
|
|
|
|
'device:;\n'
|
|
|
|
'15:1049kB:9437kB:8389kB:::boot;\n'
|
|
|
|
'1:9437kB:46.1MB:36.7MB:ext3::;\n')
|
|
|
|
disk_file_output = ('/dev/loop1: partition 1: ID=0xee, starthead 0, '
|
|
|
|
'startsector 1, 90111 sectors, extended '
|
|
|
|
'partition table (last)\011, code offset 0x48')
|
|
|
|
|
|
|
|
part_file_output = ('/dev/loop1p15: x86 boot sector, mkdosfs boot '
|
|
|
|
'message display, code offset 0x3c, OEM-ID '
|
|
|
|
'"mkfs.fat", sectors/cluster 8, root entries '
|
|
|
|
'512, sectors 16384 (volumes <=32 MB) , Media '
|
|
|
|
'descriptor 0xf8, sectors/FAT 8, heads 255, '
|
|
|
|
'serial number 0x23a08feb, unlabeled, '
|
|
|
|
'FAT (12 bit)')
|
|
|
|
|
|
|
|
# NOTE(TheJulia): File evaluates this data, so it is pointless to
|
|
|
|
# try and embed the raw bytes in the test.
|
|
|
|
dd_output = ('')
|
|
|
|
|
|
|
|
file_output = ('/dev/loop1: DOS executable (COM)\n')
|
|
|
|
|
|
|
|
mock_execute.side_effect = iter([(parted_output, ''),
|
|
|
|
(disk_file_output, ''),
|
|
|
|
(part_file_output, ''),
|
|
|
|
(dd_output, ''),
|
|
|
|
(file_output, '')])
|
|
|
|
|
|
|
|
result = image._is_bootloader_loaded(self.fake_dev)
|
|
|
|
self.assertTrue(result)
|
|
|
|
|
|
|
|
def test__is_bootloader_loaded_not_bootable(self,
|
|
|
|
mock_execute,
|
|
|
|
mock_dispatch):
|
|
|
|
parted_output = ('BYT;\n'
|
|
|
|
'/dev/loop1:46.1MB:loopback:512:512:gpt:Loopback '
|
|
|
|
'device:;\n'
|
|
|
|
'15:1049kB:9437kB:8389kB:::;\n'
|
|
|
|
'1:9437kB:46.1MB:36.7MB:ext3::;\n')
|
|
|
|
mock_execute.return_value = (parted_output, '')
|
|
|
|
result = image._is_bootloader_loaded(self.fake_dev)
|
|
|
|
self.assertFalse(result)
|
|
|
|
|
|
|
|
def test__is_bootloader_loaded_empty(self,
|
|
|
|
mock_execute,
|
|
|
|
mock_dispatch):
|
|
|
|
parted_output = ('BYT;\n'
|
|
|
|
'/dev/loop1:46.1MB:loopback:512:512:gpt:Loopback '
|
|
|
|
'device:;\n')
|
|
|
|
mock_execute.return_value = (parted_output, '')
|
|
|
|
result = image._is_bootloader_loaded(self.fake_dev)
|
|
|
|
self.assertFalse(result)
|
2019-12-02 16:56:42 +01:00
|
|
|
|
2020-03-23 07:46:48 -07:00
|
|
|
def test__is_bootloader_loaded_uefi_mode(self, mock_execute,
|
|
|
|
mock_dispatch):
|
|
|
|
|
|
|
|
mock_dispatch.return_value = hardware.BootInfo(
|
|
|
|
current_boot_mode='uefi')
|
|
|
|
result = image._is_bootloader_loaded(self.fake_dev)
|
|
|
|
self.assertFalse(result)
|
|
|
|
mock_dispatch.assert_any_call('get_boot_info')
|
|
|
|
self.assertEqual(0, mock_execute.call_count)
|
|
|
|
|
2021-02-12 14:47:16 +01:00
|
|
|
@mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
|
2020-08-26 08:35:33 -07:00
|
|
|
@mock.patch.object(os.path, 'exists', lambda *_: True)
|
|
|
|
def test__append_uefi_to_fstab_handles_error(self, mock_execute,
|
2021-02-12 14:47:16 +01:00
|
|
|
mock_dispatch,
|
|
|
|
mock_list_blk_devs):
|
2020-08-26 08:35:33 -07:00
|
|
|
with mock.patch('builtins.open', mock.mock_open()) as mock_open:
|
|
|
|
mock_open.side_effect = OSError('boom')
|
|
|
|
image._append_uefi_to_fstab(
|
|
|
|
self.fake_dir, 'abcd-efgh')
|