diff --git a/SOURCES/0013-Activate-all-wired-network-devices-with-link-in-up-s.patch b/SOURCES/0013-Activate-all-wired-network-devices-with-link-in-up-s.patch new file mode 100644 index 0000000..ac04f0c --- /dev/null +++ b/SOURCES/0013-Activate-all-wired-network-devices-with-link-in-up-s.patch @@ -0,0 +1,262 @@ +From a5cb6c787cd9329aa4d4825c350a45785859a01f Mon Sep 17 00:00:00 2001 +From: Anton Volkov +Date: Tue, 20 Feb 2024 19:38:47 +0300 +Subject: [PATCH 1/2] Activate all wired network devices with link in up state + when running interactive installation + +--- + anaconda.py | 3 + + pyanaconda/modules/network/initialization.py | 44 +++++++++ + pyanaconda/modules/network/network.py | 15 ++- + .../modules/network/network_interface.py | 9 ++ + pyanaconda/network.py | 91 +++++++++++++++++++ + 5 files changed, 161 insertions(+), 1 deletion(-) + +diff --git a/anaconda.py b/anaconda.py +index bbf801b..ae282e3 100755 +--- a/anaconda.py ++++ b/anaconda.py +@@ -516,6 +516,9 @@ if __name__ == "__main__": + # Initialize the network now, in case the display needs it + from pyanaconda.network import initialize_network, wait_for_connecting_NM_thread, wait_for_connected_NM + ++ import pyanaconda.network # @UnusedImport ++ pyanaconda.network.interactive_mode = anaconda.interactive_mode ++ + initialize_network() + # If required by user, wait for connection before starting the installation. + if opts.waitfornet: +diff --git a/pyanaconda/modules/network/initialization.py b/pyanaconda/modules/network/initialization.py +index f61b88f..dc8035a 100644 +--- a/pyanaconda/modules/network/initialization.py ++++ b/pyanaconda/modules/network/initialization.py +@@ -32,6 +32,7 @@ from pyanaconda.modules.network.ifcfg import get_ifcfg_file_of_device, find_ifcf + from pyanaconda.modules.network.device_configuration import supported_wired_device_types, \ + virtual_device_types + from pyanaconda.modules.network.utils import guard_by_system_configuration ++from pyanaconda.network import switch_all_network_devices + + log = get_module_logger(__name__) + +@@ -40,6 +41,49 @@ gi.require_version("NM", "1.0") + from gi.repository import NM + + ++class SwitchNetworkDevicesTask(Task): ++ """Task for switching all network devices ON""" ++ ++ def __init__(self, network_data, supported_devices, bootif, ifname_option_values): ++ """Create a new task. ++ ++ :param network_data: kickstart network data to be applied ++ :type: list(NetworkData) ++ :param supported_devices: list of names of supported network devices ++ :type supported_devices: list(str) ++ :param bootif: MAC addres of device to be used for --device=bootif specification ++ :type bootif: str ++ :param ifname_option_values: list of ifname boot option values ++ :type ifname_option_values: list(str) ++ """ ++ super().__init__() ++ self._network_data = network_data ++ self._supported_devices = supported_devices ++ self._bootif = bootif ++ self._ifname_option_values = ifname_option_values ++ ++ @property ++ def name(self): ++ return "Switch network devices on" ++ ++ def for_publication(self): ++ """Return a DBus representation.""" ++ return NetworkInitializationTaskInterface(self) ++ ++ @guard_by_system_configuration(return_value=[]) ++ def run(self): ++ """Run the switching network devices on. ++ ++ :returns: names of devices ++ :rtype: list(str) ++ """ ++ with nm_client_in_thread() as nm_client: ++ return self._run(nm_client) ++ ++ def _run(self, nm_client): ++ return switch_all_network_devices(nm_client) ++ ++ + class ApplyKickstartTask(Task): + """Task for application of kickstart network configuration.""" + +diff --git a/pyanaconda/modules/network/network.py b/pyanaconda/modules/network/network.py +index 1e194c3..d436190 100644 +--- a/pyanaconda/modules/network/network.py ++++ b/pyanaconda/modules/network/network.py +@@ -39,7 +39,7 @@ from pyanaconda.modules.network.ifcfg import get_kickstart_network_data, \ + get_ifcfg_file, get_ifcfg_files_content + from pyanaconda.modules.network.installation import NetworkInstallationTask, \ + ConfigureActivationOnBootTask, HostnameConfigurationTask +-from pyanaconda.modules.network.initialization import ApplyKickstartTask, \ ++from pyanaconda.modules.network.initialization import ApplyKickstartTask, SwitchNetworkDevicesTask, \ + ConsolidateInitramfsConnectionsTask, SetRealOnbootValuesFromKickstartTask, \ + DumpMissingIfcfgFilesTask + from pyanaconda.modules.network.utils import get_default_route_iface +@@ -550,6 +550,19 @@ class NetworkService(KickstartService): + self._ifname_option_values = values + log.debug("ifname boot option values are set to %s", values) + ++ def switch_network_devices_with_task(self): ++ """Switch all network devices ON ++ ++ :returns: a task switching all network devices ON ++ """ ++ supported_devices = [dev_info.device_name for dev_info in self.get_supported_devices()] ++ task = SwitchNetworkDevicesTask(self._original_network_data, ++ supported_devices, ++ self.bootif, ++ self.ifname_option_values) ++ task.succeeded_signal.connect(lambda: self.log_task_result(task, check_result=True)) ++ return task ++ + def apply_kickstart_with_task(self): + """Apply kickstart configuration which has not already been applied. + +diff --git a/pyanaconda/modules/network/network_interface.py b/pyanaconda/modules/network/network_interface.py +index 6e904ba..27e6e3d 100644 +--- a/pyanaconda/modules/network/network_interface.py ++++ b/pyanaconda/modules/network/network_interface.py +@@ -213,6 +213,15 @@ class NetworkInterface(KickstartModuleInterface): + self.implementation.consolidate_initramfs_connections_with_task() + ) + ++ def SwitchNetworkDevicesWithTask(self) -> ObjPath: ++ """Switch network devices ON ++ ++ :returns: DBus path of the task switching network devices ON ++ """ ++ return TaskContainer.to_object_path( ++ self.implementation.switch_network_devices_with_task() ++ ) ++ + def ApplyKickstartWithTask(self) -> ObjPath: + """Apply kickstart configuration which has not already been applied. + +diff --git a/pyanaconda/network.py b/pyanaconda/network.py +index d757934..f7fa48c 100644 +--- a/pyanaconda/network.py ++++ b/pyanaconda/network.py +@@ -50,6 +50,8 @@ log = get_module_logger(__name__) + + DEFAULT_HOSTNAME = "localhost.localdomain" + ++interactive_mode = False ++ + network_connected = None + network_connected_condition = threading.Condition() + +@@ -272,6 +274,91 @@ def run_network_initialization_task(task_path): + log.debug(msg) + + ++def switch_all_network_devices(client, activate=True, check_link=True, wait=True): ++ """ ++ Switch ON (or OFF) all wired network devices with link in up state. ++ Return list of device names switched ON ++ :param client: Network Manager client object ++ :param activate: True = activate (ON), False = deactivate network devices ++ :param check_link: True = activate network devices with link in up state only ++ :param wait: True = wait for network devices to become active before exiting the function ++ :rtype list(str) ++ """ ++ action = "on" if activate else "off" ++ log.debug("start switching all devices %s", action) ++ if not client: ++ log.debug("NM client not available") ++ return [] ++ devices = client.get_devices() ++ if not devices: ++ log.debug("No devices found") ++ return [] ++ activated_ifaces = get_activated_devices(client) ++ active_connections = client.get_active_connections() ++ active_uuids = set([con.get_uuid() for con in active_connections]) ++ changed = False ++ ifaces = set() ++ for device in devices: ++ if not device: ++ continue ++ switched = False ++ iface = device.get_iface() ++ if not device_type_is_supported_wired(device.get_device_type()): ++ log.debug("device %s is not wired, skipping", iface) ++ continue ++ if activate: ++ if iface in activated_ifaces: ++ log.debug("device %s activated already, skipping", iface) ++ continue ++ elif iface not in activated_ifaces: ++ log.debug("device %s not activated already, skipping", iface) ++ continue ++ # check if the link for the device is up ++ if check_link and activate: ++ try: ++ carrier = device.get_carrier() ++ except AttributeError: ++ carrier = None ++ if carrier: ++ log.debug("device %s link is up", iface) ++ else: ++ log.debug("device %s link is down", iface) ++ # skip activating device if link is down ++ continue ++ connections = device.get_available_connections() ++ if not connections: ++ log.debug("No available connections for device %s", iface) ++ continue ++ for con in connections: ++ if not con: ++ continue ++ uuid = con.get_uuid() ++ if activate: ++ if uuid in active_uuids: ++ log.debug("connection %s for device %s is active already, skipping", uuid, iface) ++ continue ++ elif uuid not in active_uuids: ++ log.debug("connection %s for device %s is not active already, skipping", uuid, iface) ++ continue ++ if activate: ++ client.activate_connection_async(con, device, None, None) ++ ifaces.add(iface) ++ else: ++ device.disconnect(None) ++ switched = changed = True ++ if switched: ++ log.info("device %s switched %s", iface, action) ++ if not changed: ++ log.debug("No devices switched %s", action) ++ if wait and ifaces: ++ if wait_for_network_devices(ifaces): ++ log.debug("waiting succeeded: devices are active") ++ else: ++ log.debug("waiting timeout has expired") ++ log.debug("finish switching all devices %s", action) ++ return list(ifaces) ++ ++ + def initialize_network(): + """Initialize networking.""" + if not conf.system.can_configure_network: +@@ -290,6 +377,10 @@ def initialize_network(): + run_network_initialization_task(network_proxy.ApplyKickstartWithTask()) + run_network_initialization_task(network_proxy.DumpMissingIfcfgFilesWithTask()) + run_network_initialization_task(network_proxy.SetRealOnbootValuesFromKickstartWithTask()) ++ if interactive_mode: ++ run_network_initialization_task(network_proxy.SwitchNetworkDevicesWithTask()) ++ else: ++ log.debug("Not activating all wired network devices in non-interactive mode") + + if network_proxy.Hostname == DEFAULT_HOSTNAME: + bootopts_hostname = hostname_from_cmdline(kernel_arguments) +-- +2.39.3 + diff --git a/SOURCES/0014-Set-autoconnect-and-autoconnect-priority-for-connect.patch b/SOURCES/0014-Set-autoconnect-and-autoconnect-priority-for-connect.patch new file mode 100644 index 0000000..99c20f1 --- /dev/null +++ b/SOURCES/0014-Set-autoconnect-and-autoconnect-priority-for-connect.patch @@ -0,0 +1,234 @@ +From 580c3dee53f0e374104af8d778457ebc526ca92d Mon Sep 17 00:00:00 2001 +From: Anton Volkov +Date: Thu, 22 Feb 2024 12:42:25 +0300 +Subject: [PATCH 2/2] Set autoconnect and autoconnect-priority for connections + of all network devices with link in up state + +--- + pyanaconda/modules/network/initialization.py | 53 +++++++++++++- + pyanaconda/modules/network/network.py | 15 +++- + .../modules/network/network_interface.py | 9 +++ + pyanaconda/network.py | 69 +++++++++++++++++++ + 4 files changed, 144 insertions(+), 2 deletions(-) + +diff --git a/pyanaconda/modules/network/initialization.py b/pyanaconda/modules/network/initialization.py +index dc8035a..5530075 100644 +--- a/pyanaconda/modules/network/initialization.py ++++ b/pyanaconda/modules/network/initialization.py +@@ -32,7 +32,7 @@ from pyanaconda.modules.network.ifcfg import get_ifcfg_file_of_device, find_ifcf + from pyanaconda.modules.network.device_configuration import supported_wired_device_types, \ + virtual_device_types + from pyanaconda.modules.network.utils import guard_by_system_configuration +-from pyanaconda.network import switch_all_network_devices ++from pyanaconda.network import switch_all_network_devices, configure_connections + + log = get_module_logger(__name__) + +@@ -41,6 +41,57 @@ gi.require_version("NM", "1.0") + from gi.repository import NM + + ++class SetAutoconnectPriorityTask(Task): ++ """ ++ Task for configuring autoconnect and autoconnect-priority for connections of ++ all network devices with link in up state ++ """ ++ ++ def __init__(self, network_data, supported_devices, bootif, ifname_option_values): ++ """Create a new task. ++ ++ :param network_data: kickstart network data to be applied ++ :type: list(NetworkData) ++ :param supported_devices: list of names of supported network devices ++ :type supported_devices: list(str) ++ :param bootif: MAC addres of device to be used for --device=bootif specification ++ :type bootif: str ++ :param ifname_option_values: list of ifname boot option values ++ :type ifname_option_values: list(str) ++ """ ++ super().__init__() ++ self._network_data = network_data ++ self._supported_devices = supported_devices ++ self._bootif = bootif ++ self._ifname_option_values = ifname_option_values ++ ++ @property ++ def name(self): ++ return "Set autoconnect and autoconnect-priority for connections of network devices with link in up state" ++ ++ def for_publication(self): ++ """Return a DBus representation.""" ++ return NetworkInitializationTaskInterface(self) ++ ++ @guard_by_system_configuration(return_value=[]) ++ def run(self): ++ """ ++ Run nmcli utility to set autoconnect and autoconnect-priority for ++ connections of network devices with link in up state ++ :returns: names of devices ++ :rtype: list(str) ++ """ ++ with nm_client_in_thread() as nm_client: ++ return self._run(nm_client) ++ ++ def _run(self, nm_client): ++ settings = { ++ "connection.autoconnect" : "yes", ++ "connection.autoconnect-priority" : "-999" ++ } ++ return configure_connections(nm_client, settings) ++ ++ + class SwitchNetworkDevicesTask(Task): + """Task for switching all network devices ON""" + +diff --git a/pyanaconda/modules/network/network.py b/pyanaconda/modules/network/network.py +index d436190..c196ac5 100644 +--- a/pyanaconda/modules/network/network.py ++++ b/pyanaconda/modules/network/network.py +@@ -40,7 +40,7 @@ from pyanaconda.modules.network.ifcfg import get_kickstart_network_data, \ + from pyanaconda.modules.network.installation import NetworkInstallationTask, \ + ConfigureActivationOnBootTask, HostnameConfigurationTask + from pyanaconda.modules.network.initialization import ApplyKickstartTask, SwitchNetworkDevicesTask, \ +- ConsolidateInitramfsConnectionsTask, SetRealOnbootValuesFromKickstartTask, \ ++ ConsolidateInitramfsConnectionsTask, SetRealOnbootValuesFromKickstartTask, SetAutoconnectPriorityTask, \ + DumpMissingIfcfgFilesTask + from pyanaconda.modules.network.utils import get_default_route_iface + from pyanaconda.modules.common.structures.network import NetworkDeviceInfo +@@ -550,6 +550,19 @@ class NetworkService(KickstartService): + self._ifname_option_values = values + log.debug("ifname boot option values are set to %s", values) + ++ def set_autoconnect_priority_with_task(self): ++ """ ++ Set autoconnect and autoconnect-priority for connections of network devices with link in up state ++ :returns: a task configuring autoconnect and autoconnect-priority for all network devices ++ """ ++ supported_devices = [dev_info.device_name for dev_info in self.get_supported_devices()] ++ task = SetAutoconnectPriorityTask(self._original_network_data, ++ supported_devices, ++ self.bootif, ++ self.ifname_option_values) ++ task.succeeded_signal.connect(lambda: self.log_task_result(task, check_result=True)) ++ return task ++ + def switch_network_devices_with_task(self): + """Switch all network devices ON + +diff --git a/pyanaconda/modules/network/network_interface.py b/pyanaconda/modules/network/network_interface.py +index 27e6e3d..52b7b48 100644 +--- a/pyanaconda/modules/network/network_interface.py ++++ b/pyanaconda/modules/network/network_interface.py +@@ -213,6 +213,15 @@ class NetworkInterface(KickstartModuleInterface): + self.implementation.consolidate_initramfs_connections_with_task() + ) + ++ def SetAutoconnectPriorityWithTask(self) -> ObjPath: ++ """Set autoconnect and autoconnect-priority for connections of network devices with link in up state ++ ++ :returns: DBus path of the task switching network devices ON ++ """ ++ return TaskContainer.to_object_path( ++ self.implementation.set_autoconnect_priority_with_task() ++ ) ++ + def SwitchNetworkDevicesWithTask(self) -> ObjPath: + """Switch network devices ON + +diff --git a/pyanaconda/network.py b/pyanaconda/network.py +index f7fa48c..7179c19 100644 +--- a/pyanaconda/network.py ++++ b/pyanaconda/network.py +@@ -46,6 +46,8 @@ from pyanaconda.modules.common.structures.network import NetworkDeviceInfo + from pyanaconda.modules.common.util import is_module_available + from pyanaconda.anaconda_loggers import get_module_logger + ++import subprocess ++ + log = get_module_logger(__name__) + + DEFAULT_HOSTNAME = "localhost.localdomain" +@@ -274,6 +276,72 @@ def run_network_initialization_task(task_path): + log.debug(msg) + + ++def configure_connections(client, settings, check_link=True): ++ """ ++ Configure connection parameters for all wired network devices with link in up state. ++ Return list of device names affected ++ :param client: Network Manager client object ++ :param settings: dict(str, str) = {name:value} of the setting to configure ++ :param check_link: True = handle network devices with link in up state only ++ :rtype list(str) ++ """ ++ log.debug("start configuring autoconnect for all network devices with link in up state") ++ if not client: ++ log.debug("NM client not available") ++ return [] ++ devices = client.get_devices() ++ if not devices: ++ log.debug("No devices found") ++ return [] ++ if not settings: ++ log.debug("No settings passed") ++ return [] ++ changed = False ++ ifaces = set() ++ for device in devices: ++ if not device: ++ continue ++ switched = False ++ iface = device.get_iface() ++ if not device_type_is_supported_wired(device.get_device_type()): ++ log.debug("device %s is not wired, skipping", iface) ++ continue ++ # check if the link for the device is up ++ if check_link: ++ try: ++ carrier = device.get_carrier() ++ except AttributeError: ++ carrier = None ++ if carrier: ++ log.debug("device %s link is up", iface) ++ else: ++ log.debug("device %s link is down", iface) ++ # skip modifying the autoconnect.priority setting for the device if link is down ++ continue ++ connections = device.get_available_connections() ++ if not connections: ++ log.debug("No available connections for device %s", iface) ++ continue ++ for con in connections: ++ if not con: ++ continue ++ uuid = con.get_uuid() ++ cmd_line = ["nmcli", "connection", "modify", "uuid", uuid] ++ for setting_name in settings: ++ setting_value = settings[setting_name] ++ cmd_line.extend([setting_name, setting_value]) ++ p = subprocess.run(cmd_line, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=False, close_fds=True) ++ log.debug("update settings for connection %s for device %s, nmcli exit code = %s", uuid, iface, str(p.returncode)) ++ ifaces.add(iface) ++ switched = changed = True ++ if switched: ++ log.info("connection settings for device %s updated", iface) ++ if not changed: ++ log.debug("No settings for devices updated") ++ log.debug("finish configuring autoconnect for all network devices with link in up state") ++ return list(ifaces) ++ ++ + def switch_all_network_devices(client, activate=True, check_link=True, wait=True): + """ + Switch ON (or OFF) all wired network devices with link in up state. +@@ -379,6 +447,7 @@ def initialize_network(): + run_network_initialization_task(network_proxy.SetRealOnbootValuesFromKickstartWithTask()) + if interactive_mode: + run_network_initialization_task(network_proxy.SwitchNetworkDevicesWithTask()) ++ run_network_initialization_task(network_proxy.SetAutoconnectPriorityWithTask()) + else: + log.debug("Not activating all wired network devices in non-interactive mode") + +-- +2.39.3 + diff --git a/SPECS/anaconda.spec b/SPECS/anaconda.spec index c838d0e..8bc1bfe 100644 --- a/SPECS/anaconda.spec +++ b/SPECS/anaconda.spec @@ -1,7 +1,7 @@ Summary: Graphical system installer Name: anaconda Version: 33.16.9.4 -Release: 1%{?dist}.inferit.4 +Release: 1%{?dist}.inferit.5 License: GPLv2+ and MIT URL: http://fedoraproject.org/wiki/Anaconda @@ -23,6 +23,8 @@ Patch9: 0009-MSVSphere-Adaptation-Patch.patch Patch10: 0010-Fix-smt-url.patch Patch11: 0011-Enable-administrator-by-default.patch Patch12: 0012-Backport-bugfixes-for-keyboard-layout.patch +Patch13: 0013-Activate-all-wired-network-devices-with-link-in-up-s.patch +Patch14: 0014-Set-autoconnect-and-autoconnect-priority-for-connect.patch # Versions of required components (done so we make sure the buildrequires # match the requires versions of things). @@ -384,6 +386,9 @@ desktop-file-install --dir=%{buildroot}%{_datadir}/applications %{buildroot}%{_d %{_prefix}/libexec/anaconda/dd_* %changelog +* Fri Feb 23 2024 Arkady L. Shane - 33.16.9.4-1.inferit.5 +- Activate network interfaces in anaconda + * Tue Feb 13 2024 Arkady L. Shane - 33.16.9.4-1.inferit.4 - Fix keyboard layout order