Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: add possibility to use net.naming-scheme #1215

Merged
merged 3 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions repos/system_upgrade/common/actors/addupgradebootentry/actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
FirmwareFacts,
GrubConfigError,
KernelCmdline,
LateTargetKernelCmdlineArgTasks,
LiveImagePreparationInfo,
LiveModeArtifacts,
LiveModeConfig,
TargetKernelCmdlineArgTasks,
TransactionDryRun
TransactionDryRun,
UpgradeKernelCmdlineArgTasks
)
from leapp.tags import InterimPreparationPhaseTag, IPUWorkflowTag

Expand All @@ -33,9 +35,11 @@ class AddUpgradeBootEntry(Actor):
LiveModeArtifacts,
LiveModeConfig,
KernelCmdline,
TransactionDryRun
TransactionDryRun,
TargetKernelCmdlineArgTasks,
UpgradeKernelCmdlineArgTasks
)
produces = (TargetKernelCmdlineArgTasks,)
produces = (LateTargetKernelCmdlineArgTasks,)
tags = (IPUWorkflowTag, InterimPreparationPhaseTag)

def process(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@
BootContent,
KernelCmdline,
KernelCmdlineArg,
LateTargetKernelCmdlineArgTasks,
LiveImagePreparationInfo,
LiveModeArtifacts,
LiveModeConfig,
TargetKernelCmdlineArgTasks
TargetKernelCmdlineArgTasks,
UpgradeKernelCmdlineArgTasks
)


def collect_boot_args(livemode_enabled):
def collect_upgrade_kernel_args(livemode_enabled):
args = {
'enforcing': '0',
'rd.plymouth': '0',
Expand All @@ -34,7 +36,10 @@ def collect_boot_args(livemode_enabled):
livemode_args = construct_cmdline_args_for_livemode()
args.update(livemode_args)

return args
upgrade_kernel_args = collect_set_of_kernel_args_from_msgs(UpgradeKernelCmdlineArgTasks, 'to_add')
args.update(upgrade_kernel_args)

return set(args.items())


def collect_undesired_args(livemode_enabled):
Expand All @@ -43,11 +48,11 @@ def collect_undesired_args(livemode_enabled):
args = dict(zip(('ro', 'rhgb', 'quiet'), itertools.repeat(None)))
args['rd.lvm.lv'] = _get_rdlvm_arg_values()

return args
return set(args.items())


def format_grubby_args_from_args_dict(args_dict):
""" Format the given args dictionary in a form required by grubby's --args. """
def format_grubby_args_from_args_set(args_dict):
""" Format the given args set in a form required by grubby's --args. """

def fmt_single_arg(arg_pair):
key, value = arg_pair
Expand All @@ -65,7 +70,7 @@ def flatten_arguments(arg_pair):
else:
yield (key, value) # Just a single (key, value) pair

arg_sequence = itertools.chain(*(flatten_arguments(arg_pair) for arg_pair in args_dict.items()))
arg_sequence = itertools.chain(*(flatten_arguments(arg_pair) for arg_pair in args_dict))

# Sorting should be fine as only values can be None, but we cannot have a (key, None) and (key, value) in
# the dictionary at the same time.
Expand All @@ -78,7 +83,7 @@ def flatten_arguments(arg_pair):
def figure_out_commands_needed_to_add_entry(kernel_path, initramfs_path, args_to_add, args_to_remove):
boot_entry_modification_commands = []

args_to_add_str = format_grubby_args_from_args_dict(args_to_add)
args_to_add_str = format_grubby_args_from_args_set(args_to_add)

create_entry_cmd = [
'/usr/sbin/grubby',
Expand All @@ -93,7 +98,7 @@ def figure_out_commands_needed_to_add_entry(kernel_path, initramfs_path, args_to

# We need to update root= param separately, since we cannot do it during --add-kernel with --copy-default.
# This is likely a bug in grubby.
root_param_value = args_to_add.get('root', None)
root_param_value = dict(args_to_add).get('root', None)
if root_param_value:
enforce_root_param_for_the_entry_cmd = [
'/usr/sbin/grubby',
Expand All @@ -103,7 +108,7 @@ def figure_out_commands_needed_to_add_entry(kernel_path, initramfs_path, args_to
boot_entry_modification_commands.append(enforce_root_param_for_the_entry_cmd)

if args_to_remove:
args_to_remove_str = format_grubby_args_from_args_dict(args_to_remove)
args_to_remove_str = format_grubby_args_from_args_set(args_to_remove)
remove_undesired_args_cmd = [
'/usr/sbin/grubby',
'--update-kernel', kernel_path,
Expand All @@ -113,18 +118,55 @@ def figure_out_commands_needed_to_add_entry(kernel_path, initramfs_path, args_to
return boot_entry_modification_commands


def collect_set_of_kernel_args_from_msgs(msg_type, arg_list_field_name):
cmdline_modification_msgs = api.consume(msg_type)
lists_of_args_to_add = (getattr(msg, arg_list_field_name, []) for msg in cmdline_modification_msgs)
args = itertools.chain(*lists_of_args_to_add)
return set((arg.key, arg.value) for arg in args)


def emit_removal_of_args_meant_only_for_upgrade_kernel(added_upgrade_kernel_args):
"""
Emit message requesting removal of upgrade kernel args that should not be on the target kernel.

Target kernel args are created by copying the args of the booted (upgrade) kernel. Therefore,
we need to explicitly modify the target kernel cmdline, removing what should not have been copied.
"""
target_args_to_add = collect_set_of_kernel_args_from_msgs(TargetKernelCmdlineArgTasks, 'to_add')
actual_kernel_args = collect_set_of_kernel_args_from_msgs(KernelCmdline, 'parameters')

# actual_kernel_args should not be changed during upgrade, unless explicitly removed by
# TargetKernelCmdlineArgTasks.to_remove, but that is handled by some other upgrade component. We just want
# to make sure we remove what was not on the source system and that we don't overwrite args to be added to target.
args_not_present_on_target_kernel = added_upgrade_kernel_args - actual_kernel_args - target_args_to_add

# We remove only what we've added and what will not be already removed by someone else.
args_to_remove = [KernelCmdlineArg(key=arg[0], value=arg[1]) for arg in args_not_present_on_target_kernel]

if args_to_remove:
msg = ('Following upgrade kernel args were added, but they should not be present '
'on target cmdline: `%s`, requesting removal.')
api.current_logger().info(msg, args_not_present_on_target_kernel)
args_sorted = sorted(args_to_remove, key=lambda arg: arg.key)
MichalHe marked this conversation as resolved.
Show resolved Hide resolved
api.produce(LateTargetKernelCmdlineArgTasks(to_remove=args_sorted))


def add_boot_entry(configs=None):
kernel_dst_path, initram_dst_path = get_boot_file_paths()

_remove_old_upgrade_boot_entry(kernel_dst_path, configs=configs)

livemode_enabled = next(api.consume(LiveImagePreparationInfo), None) is not None

cmdline_args = collect_boot_args(livemode_enabled)
# We have to keep the desired and unwanted args separate and modify cmline in two separate grubby calls. Merging
# these sets and trying to execute only a single command would leave the unwanted cmdline args present if they
# are present on the original system.
added_cmdline_args = collect_upgrade_kernel_args(livemode_enabled)
undesired_cmdline_args = collect_undesired_args(livemode_enabled)

commands_to_run = figure_out_commands_needed_to_add_entry(kernel_dst_path,
initram_dst_path,
args_to_add=cmdline_args,
args_to_add=added_cmdline_args,
args_to_remove=undesired_cmdline_args)

def run_commands_adding_entry(extra_command_suffix=None):
Expand All @@ -146,16 +188,8 @@ def run_commands_adding_entry(extra_command_suffix=None):
# See https://bugzilla.redhat.com/show_bug.cgi?id=1764306
run(['/usr/sbin/zipl'])

if 'debug' in cmdline_args:
# The kernelopts for target kernel are generated based on the cmdline used in the upgrade initramfs,
# therefore, if we enabled debug above, and the original system did not have the debug kernelopt, we
# need to explicitly remove it from the target os boot entry.
# NOTE(mhecko): This will also unconditionally remove debug kernelopt if the source system used it.
api.produce(TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='debug')]))

# NOTE(mmatuska): This will remove the option even if the source system had it set.
# However enforcing=0 shouldn't be set persistently anyway.
api.produce(TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='enforcing', value='0')]))
effective_upgrade_kernel_args = added_cmdline_args - undesired_cmdline_args
emit_removal_of_args_meant_only_for_upgrade_kernel(effective_upgrade_kernel_args)

except CalledProcessError as e:
raise StopActorExecutionError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
BootContent,
KernelCmdline,
KernelCmdlineArg,
LateTargetKernelCmdlineArgTasks,
LiveModeArtifacts,
LiveModeConfig,
TargetKernelCmdlineArgTasks
Expand Down Expand Up @@ -82,8 +83,10 @@ def get_boot_file_paths_mocked():
assert addupgradebootentry.run.args[0] == run_args.args_remove
assert addupgradebootentry.run.args[1] == run_args.args_add
assert api.produce.model_instances == [
TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='debug')]),
TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='enforcing', value='0')])
LateTargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='debug'),
KernelCmdlineArg(key='enforcing', value='0'),
KernelCmdlineArg(key='plymouth.enable', value='0'),
KernelCmdlineArg(key='rd.plymouth', value='0')])
]

if run_args.args_zipl:
Expand All @@ -103,16 +106,16 @@ def get_boot_file_paths_mocked():
CurrentActorMocked(envars={'LEAPP_DEBUG': str(int(is_leapp_invoked_with_debug))}))

addupgradebootentry.add_boot_entry()
assert len(api.produce.model_instances) == 1

expected_produced_messages = []
if is_leapp_invoked_with_debug:
expected_produced_messages = [TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='debug')])]

expected_produced_messages.append(
TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='enforcing', value='0')])
)
produced_msg = api.produce.model_instances[0]
assert isinstance(produced_msg, LateTargetKernelCmdlineArgTasks)

assert api.produce.model_instances == expected_produced_messages
debug_kernel_cmline_arg = KernelCmdlineArg(key='debug')
if is_leapp_invoked_with_debug:
assert debug_kernel_cmline_arg in produced_msg.to_remove
else:
assert debug_kernel_cmline_arg not in produced_msg.to_remove


def test_add_boot_entry_configs(monkeypatch):
Expand All @@ -132,8 +135,10 @@ def get_boot_file_paths_mocked():
assert addupgradebootentry.run.args[2] == run_args_add + ['-c', CONFIGS[0]]
assert addupgradebootentry.run.args[3] == run_args_add + ['-c', CONFIGS[1]]
assert api.produce.model_instances == [
TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='debug')]),
TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='enforcing', value='0')]),
LateTargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='debug'),
KernelCmdlineArg(key='enforcing', value='0'),
KernelCmdlineArg(key='plymouth.enable', value='0'),
KernelCmdlineArg(key='rd.plymouth', value='0')])
]


Expand Down Expand Up @@ -183,7 +188,7 @@ def test_fix_grub_config_error(monkeypatch, error_type, test_file_name):
(False, False),
)
)
def test_collect_boot_args(monkeypatch, is_debug_enabled, network_enablement_type):
def test_collect_upgrade_kernel_args(monkeypatch, is_debug_enabled, network_enablement_type):
env_vars = {'LEAPP_DEBUG': str(int(is_debug_enabled))}
if network_enablement_type:
env_vars['LEAPP_DEVEL_INITRAM_NETWORK'] = network_enablement_type
Expand All @@ -192,7 +197,8 @@ def test_collect_boot_args(monkeypatch, is_debug_enabled, network_enablement_typ
monkeypatch.setattr(addupgradebootentry, 'construct_cmdline_args_for_livemode',
lambda *args: {'livemodearg': 'value'})

args = addupgradebootentry.collect_boot_args(livemode_enabled=True)
arg_set = addupgradebootentry.collect_upgrade_kernel_args(livemode_enabled=True)
args = dict(arg_set)

assert args['enforcing'] == '0'
assert args['rd.plymouth'] == '0'
Expand Down Expand Up @@ -320,16 +326,3 @@ def readlink_mock(path):
uuid = addupgradebootentry._get_device_uuid(path)

assert uuid == 'MY_UUID1'


@pytest.mark.parametrize(
('args', 'expected_result'),
(
([('argA', 'val'), ('argB', 'valB'), ('argC', None), ], 'argA=val argB=valB argC'),
([('argA', ('val1', 'val2'))], 'argA=val1 argA=val2')
)
)
def test_format_grubby_args_from_args_dict(args, expected_result):
actual_result = addupgradebootentry.format_grubby_args_from_args_dict(dict(args))

assert actual_result == expected_result
16 changes: 14 additions & 2 deletions repos/system_upgrade/common/actors/kernelcmdlineconfig/actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
from leapp.actors import Actor
from leapp.exceptions import StopActorExecutionError
from leapp.libraries.actor import kernelcmdlineconfig
from leapp.models import FirmwareFacts, InstalledTargetKernelInfo, KernelCmdlineArg, TargetKernelCmdlineArgTasks
from leapp.models import (
FirmwareFacts,
InstalledTargetKernelInfo,
KernelCmdlineArg,
LateTargetKernelCmdlineArgTasks,
TargetKernelCmdlineArgTasks
)
from leapp.reporting import Report
from leapp.tags import FinalizationPhaseTag, IPUWorkflowTag

Expand All @@ -14,7 +20,13 @@ class KernelCmdlineConfig(Actor):
"""

name = 'kernelcmdlineconfig'
consumes = (KernelCmdlineArg, InstalledTargetKernelInfo, FirmwareFacts, TargetKernelCmdlineArgTasks)
consumes = (
KernelCmdlineArg,
InstalledTargetKernelInfo,
FirmwareFacts,
LateTargetKernelCmdlineArgTasks,
TargetKernelCmdlineArgTasks
)
produces = (Report,)
tags = (FinalizationPhaseTag, IPUWorkflowTag)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import itertools
import re

from leapp import reporting
from leapp.exceptions import StopActorExecutionError
from leapp.libraries import stdlib
from leapp.libraries.common.config import architecture, version
from leapp.libraries.stdlib import api
from leapp.models import InstalledTargetKernelInfo, KernelCmdlineArg, TargetKernelCmdlineArgTasks
from leapp.models import (
InstalledTargetKernelInfo,
KernelCmdlineArg,
LateTargetKernelCmdlineArgTasks,
TargetKernelCmdlineArgTasks
)

KERNEL_CMDLINE_FILE = "/etc/kernel/cmdline"

Expand Down Expand Up @@ -71,7 +77,9 @@ def retrieve_arguments_to_modify():
kernelargs_msgs_to_add = list(api.consume(KernelCmdlineArg))
kernelargs_msgs_to_remove = []

for target_kernel_arg_task in api.consume(TargetKernelCmdlineArgTasks):
modification_msgs = itertools.chain(api.consume(TargetKernelCmdlineArgTasks),
api.consume(LateTargetKernelCmdlineArgTasks))
for target_kernel_arg_task in modification_msgs:
kernelargs_msgs_to_add.extend(target_kernel_arg_task.to_add)
kernelargs_msgs_to_remove.extend(target_kernel_arg_task.to_remove)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
import re

from leapp.libraries.common.config import get_env
from leapp.libraries.common.config import get_env, version
from leapp.libraries.stdlib import api
from leapp.models import (
InitrdIncludes,
Expand Down Expand Up @@ -39,6 +39,10 @@ def generate_link_file(interface):

@suppress_deprecation(InitrdIncludes)
def process():
if get_env('LEAPP_USE_NET_NAMING_SCHEMES', '0') == '1' and version.get_target_major_version() == '9':
# We can use this only for 8>9, for now
api.current_logger().info('Skipping generation of .link files renaming NICs as LEAPP_USE_NET_NAMING_SCHEMES=1')
return

if get_env('LEAPP_NO_NETWORK_RENAMING', '0') == '1':
api.current_logger().info(
Expand Down
21 changes: 21 additions & 0 deletions repos/system_upgrade/common/models/kernelcmdlineargs.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,27 @@ class TargetKernelCmdlineArgTasks(Model):
to_remove = fields.List(fields.Model(KernelCmdlineArg), default=[])


class LateTargetKernelCmdlineArgTasks(Model):
"""
Desired modifications of the target kernel args produced later in the upgrade process.

Defined to prevent loops in the actor dependency graph.
"""
topic = SystemInfoTopic

to_add = fields.List(fields.Model(KernelCmdlineArg), default=[])
to_remove = fields.List(fields.Model(KernelCmdlineArg), default=[])


class UpgradeKernelCmdlineArgTasks(Model):
"""
Modifications of the upgrade kernel cmdline.
"""
topic = SystemInfoTopic

to_add = fields.List(fields.Model(KernelCmdlineArg), default=[])


class KernelCmdline(Model):
"""
Kernel command line parameters the system was booted with
Expand Down
Loading