!292 sync from sp2
From: @sun_hai_10 Reviewed-by: @t_feng Signed-off-by: @t_feng
This commit is contained in:
commit
4df7cc567d
@ -1,7 +1,7 @@
|
||||
%define _empty_manifest_terminate_build 0
|
||||
Name: anaconda
|
||||
Version: 36.16.5
|
||||
Release: 15
|
||||
Release: 18
|
||||
Summary: Graphical system installer
|
||||
License: GPLv2+ and MIT
|
||||
URL: http://fedoraproject.org/wiki/Anaconda
|
||||
@ -37,10 +37,17 @@ Patch9015: bugfix-change-gnome-kiosk-to-use-metacity.patch
|
||||
Patch9016: bugfix-add-log-and-background.patch
|
||||
Patch9017: bugfix-add-SM3-with-tui.patch
|
||||
Patch9018: bugfix-change-product-name-do-not-with-upper.patch
|
||||
Patch6003: backport-dracut-handle-compressed-kernel-modules.patch
|
||||
Patch6004: backport-Ignore-SIGINT-in-D-Bus-launcher-and-x11-too.patch
|
||||
Patch6005: backport-network-use-separate-main-conext-for-NM-client-in-threads.patch
|
||||
Patch6006: backport-Sort-RPM-versions-via-rpm.labelCompare-and-not-via-p.patch
|
||||
|
||||
Patch9019: bugfix-adapt-active-connection-without-interface-name.patch
|
||||
|
||||
Patch9020: bugfix-password-tooltip-text-adapt-language.patch
|
||||
|
||||
Patch9021: bugfix-revert-Unify-GRUB-configuration-file-location-across-all-platforms.patch
|
||||
|
||||
%define dasbusver 1.3
|
||||
%define dbusver 1.2.3
|
||||
%define dnfver 3.6.0
|
||||
@ -282,6 +289,27 @@ update-desktop-database &> /dev/null || :
|
||||
%{_prefix}/libexec/anaconda/dd_*
|
||||
|
||||
%changelog
|
||||
* Fri Jun 09 2023 sunhai <sunhai10@huawei.com> - 36.16.5-18
|
||||
- Type:bugfix
|
||||
- ID:NA
|
||||
- SUG:NA
|
||||
- DESC: set grub configuration file is as original
|
||||
|
||||
* Fri Jun 09 2023 sunhai <sunhai10@huawei.com> - 36.16.5-17
|
||||
- Type:bugfix
|
||||
- ID:NA
|
||||
- SUG:NA
|
||||
- DESC: Ignore SIGINT in D Bus launcher and x11 too
|
||||
network use separate main conext for NM client in threads
|
||||
dracut handle compressed kernel modules
|
||||
Sort RPM versions via rpm.labelCompare
|
||||
|
||||
* Sat Jun 03 2023 sunhai <sunhai10@huawei.com> - 36.16.5-16
|
||||
- Type:bugfix
|
||||
- ID:NA
|
||||
- SUG:NA
|
||||
- DESC: fix gui hostname warn info
|
||||
|
||||
* Tue May 16 2023 Chenxi Mao <chenxi.mao@suse.com> - 36.16.5-15
|
||||
- Type:bugfix
|
||||
- ID:NA
|
||||
|
||||
76
backport-Ignore-SIGINT-in-D-Bus-launcher-and-x11-too.patch
Normal file
76
backport-Ignore-SIGINT-in-D-Bus-launcher-and-x11-too.patch
Normal file
@ -0,0 +1,76 @@
|
||||
From d8060d01a01e3d5b187ae4388f10b0d0c2c0c4f3 Mon Sep 17 00:00:00 2001
|
||||
From: iasunsea <iasunsea@sina.com>
|
||||
Date: Tue, 6 Dec 2022 18:24:50 +0800
|
||||
Subject: [PATCH] Ignore SIGINT in D-Bus launcher and x11 too
|
||||
|
||||
When we do install, especially use TUI to install, we some time have take
|
||||
a mistake to put "CTRL+C", then there will be stop with traceback. And we
|
||||
know the main process have shielded SIGINT, so we to shield subprocesses also.
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/rhinstaller/anaconda/commit/d8060d01a01e3d5b187ae4388f10b0d0c2c0c4f3
|
||||
---
|
||||
pyanaconda/core/startup/dbus_launcher.py | 6 ++++++
|
||||
pyanaconda/display.py | 8 +++++++-
|
||||
2 files changed, 13 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pyanaconda/core/startup/dbus_launcher.py b/pyanaconda/core/startup/dbus_launcher.py
|
||||
index 2881c28..a866df0 100644
|
||||
--- a/pyanaconda/core/startup/dbus_launcher.py
|
||||
+++ b/pyanaconda/core/startup/dbus_launcher.py
|
||||
@@ -24,6 +24,7 @@
|
||||
# Author(s): Jiri Konecny <jkonecny@redhat.com>
|
||||
#
|
||||
import os
|
||||
+import signal
|
||||
from subprocess import TimeoutExpired
|
||||
|
||||
from pyanaconda.core.configuration.anaconda import conf
|
||||
@@ -109,6 +110,10 @@ class AnacondaDBusLauncher(object):
|
||||
"--syslog",
|
||||
"--config-file={}".format(ANACONDA_BUS_CONF_FILE)
|
||||
]
|
||||
+
|
||||
+ def dbus_preexec():
|
||||
+ # to set dbus subprocess SIGINT handler
|
||||
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||
|
||||
self._log_file = open('/tmp/dbus.log', 'a')
|
||||
self._dbus_daemon_process = startProgram(
|
||||
@@ -117,6 +122,7 @@ class AnacondaDBusLauncher(object):
|
||||
env_add={"LANG": DEFAULT_LANG},
|
||||
env_prune=["LANGUAGE", "LC_ALL", "LC_MESSAGES"],
|
||||
reset_lang=False,
|
||||
+ preexec_fn=dbus_preexec
|
||||
)
|
||||
|
||||
if self._dbus_daemon_process.poll() is not None:
|
||||
diff --git a/pyanaconda/display.py b/pyanaconda/display.py
|
||||
index ddf24fb..ed163e7 100644
|
||||
--- a/pyanaconda/display.py
|
||||
+++ b/pyanaconda/display.py
|
||||
@@ -24,6 +24,7 @@ import subprocess
|
||||
import time
|
||||
import textwrap
|
||||
import pkgutil
|
||||
+import signal
|
||||
|
||||
from pyanaconda.core.configuration.anaconda import conf
|
||||
from pyanaconda.core.process_watchers import WatchProcesses
|
||||
@@ -192,8 +193,13 @@ def do_startup_x11_actions():
|
||||
else:
|
||||
xdg_data_dirs = datadir + '/window-manager:/usr/share'
|
||||
|
||||
+ def x11_preexec():
|
||||
+ # to set GUI subprocess SIGINT handler
|
||||
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||
+
|
||||
childproc = util.startProgram(["metacity", "--display", ":1", "--sm-disable"],
|
||||
- env_add={'XDG_DATA_DIRS': xdg_data_dirs})
|
||||
+ env_add={'XDG_DATA_DIRS': xdg_data_dirs},
|
||||
+ preexec_fn=x11_preexec)
|
||||
WatchProcesses.watch_process(childproc, "metacity")
|
||||
|
||||
|
||||
--
|
||||
2.23.0
|
||||
@ -0,0 +1,109 @@
|
||||
From 1742188518c9af7e3cd060a26f3a3b1e4cb61e91 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
|
||||
Date: Fri, 3 Feb 2023 21:46:15 +0100
|
||||
Subject: [PATCH] Sort RPM versions via rpm.labelCompare() and not via
|
||||
packaging.version.LegacyVersion()
|
||||
|
||||
Packaging 22+ removed the long-deprecated packaging.version.LegacyVersion class.
|
||||
The packaging.version library is intended to parse Python (PEP 440) versions,
|
||||
not arbitrary versions and definitively not RPM versions.
|
||||
|
||||
Even if LegacyVersion was still available, it may produce incorrect results
|
||||
if the version contains ~, ^ or other characters with special meaning in RPM.
|
||||
|
||||
This assumes the Python rpm module is always available.
|
||||
If that assumption is wrong
|
||||
the logic from rpm.labelCompare() needs to be reimplemented instead.
|
||||
|
||||
Reference:https://github.com/rhinstaller/anaconda/commit/1742188518c9af7e3cd060a26f3a3b1e4cb61e91
|
||||
Conflict:NA
|
||||
---
|
||||
pyanaconda/core/payload.py | 5 +++++
|
||||
pyanaconda/modules/payloads/base/utils.py | 13 ++-----------
|
||||
pyanaconda/modules/storage/checker/utils.py | 4 ++--
|
||||
3 files changed, 9 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/core/payload.py b/pyanaconda/core/payload.py
|
||||
index 17277b7..7817150 100644
|
||||
--- a/pyanaconda/core/payload.py
|
||||
+++ b/pyanaconda/core/payload.py
|
||||
@@ -15,11 +15,16 @@
|
||||
# License and may only be used or replicated with the express permission of
|
||||
# Red Hat, Inc.
|
||||
#
|
||||
+from functools import cmp_to_key
|
||||
from urllib.parse import quote, unquote
|
||||
|
||||
+import rpm
|
||||
+
|
||||
from pyanaconda.core.i18n import _
|
||||
from pyanaconda.core.regexes import URL_PARSE
|
||||
|
||||
+rpm_version_key = cmp_to_key(rpm.labelCompare)
|
||||
+
|
||||
|
||||
def parse_nfs_url(nfs_url):
|
||||
"""Parse NFS URL into components.
|
||||
diff --git a/pyanaconda/modules/payloads/base/utils.py b/pyanaconda/modules/payloads/base/utils.py
|
||||
index 738ae66..5f19b57 100644
|
||||
--- a/pyanaconda/modules/payloads/base/utils.py
|
||||
+++ b/pyanaconda/modules/payloads/base/utils.py
|
||||
@@ -17,13 +17,11 @@
|
||||
# License and may only be used or replicated with the express permission of
|
||||
# Red Hat, Inc.
|
||||
#
|
||||
-import functools
|
||||
import os
|
||||
import stat
|
||||
|
||||
-from packaging.version import LegacyVersion as parse_version
|
||||
-
|
||||
from pyanaconda.anaconda_loggers import get_module_logger
|
||||
+from pyanaconda.core.payload import rpm_version_key
|
||||
log = get_module_logger(__name__)
|
||||
|
||||
|
||||
@@ -70,11 +68,4 @@ def get_dir_size(directory):
|
||||
|
||||
def sort_kernel_version_list(kernel_version_list):
|
||||
"""Sort the given kernel version list."""
|
||||
- kernel_version_list.sort(key=functools.cmp_to_key(_compare_versions))
|
||||
-
|
||||
-
|
||||
-def _compare_versions(v1, v2):
|
||||
- """Compare two version number strings."""
|
||||
- first_version = parse_version(v1)
|
||||
- second_version = parse_version(v2)
|
||||
- return (first_version > second_version) - (first_version < second_version)
|
||||
+ kernel_version_list.sort(key=rpm_version_key)
|
||||
diff --git a/pyanaconda/modules/storage/checker/utils.py b/pyanaconda/modules/storage/checker/utils.py
|
||||
index 180c351..9ccd398 100644
|
||||
--- a/pyanaconda/modules/storage/checker/utils.py
|
||||
+++ b/pyanaconda/modules/storage/checker/utils.py
|
||||
@@ -20,7 +20,6 @@ gi.require_version("BlockDev", "2.0")
|
||||
from gi.repository import BlockDev as blockdev
|
||||
|
||||
from collections import defaultdict
|
||||
-from packaging.version import LegacyVersion as parse_version
|
||||
|
||||
from blivet import arch, util
|
||||
from blivet.devicefactory import get_device_type
|
||||
@@ -34,6 +33,7 @@ from pyanaconda.core.constants import productName, STORAGE_REFORMAT_BLOCKLIST, \
|
||||
STORAGE_LUKS2_MIN_RAM, STORAGE_ROOT_DEVICE_TYPES, STORAGE_REQ_PARTITION_SIZES, \
|
||||
STORAGE_MUST_NOT_BE_ON_ROOT
|
||||
from pyanaconda.core.i18n import _
|
||||
+from pyanaconda.core.payload import rpm_version_key
|
||||
from pyanaconda.core.storage import DEVICE_TEXT_MAP
|
||||
from pyanaconda.modules.storage.platform import platform
|
||||
|
||||
@@ -259,7 +259,7 @@ def _check_opal_firmware_kernel_version(detected_version, required_version):
|
||||
"""
|
||||
try:
|
||||
if detected_version and required_version:
|
||||
- return parse_version(detected_version) >= parse_version(required_version)
|
||||
+ return rpm_version_key(detected_version) >= rpm_version_key(required_version)
|
||||
except Exception as e: # pylint: disable=broad-except
|
||||
log.warning("Couldn't check the firmware kernel version: %s", str(e))
|
||||
|
||||
--
|
||||
2.23.0
|
||||
47
backport-dracut-handle-compressed-kernel-modules.patch
Normal file
47
backport-dracut-handle-compressed-kernel-modules.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From c4a388d3956088c96631b72f0631db2a380127b0 Mon Sep 17 00:00:00 2001
|
||||
From: Mikhail Novosyolov <m.novosyolov@rosalinux.ru>
|
||||
Date: Fri, 10 Jun 2022 22:03:43 +0300
|
||||
Subject: [PATCH] dracut: handle compressed kernel modules
|
||||
|
||||
Compressed kernel modules could not be loaded.
|
||||
Now both compressed and not compressed ones will be loaded.
|
||||
|
||||
$ uname -r
|
||||
5.10.74-generic-2rosa2021.1-x86_64
|
||||
$ ls -1v /lib/modules/$(uname -r)/kernel/drivers/scsi/device_handler/
|
||||
scsi_dh_alua.ko.zst
|
||||
scsi_dh_emc.ko.zst
|
||||
scsi_dh_hp_sw.ko.zst
|
||||
scsi_dh_rdac.ko.zst
|
||||
|
||||
Replaces https://github.com/rhinstaller/anaconda/pull/3501
|
||||
Noted by slava86@
|
||||
Reference:https://github.com/rhinstaller/anaconda/commit/c4a388d3956088c96631b72f0631db2a380127b0
|
||||
Conflict:NA
|
||||
---
|
||||
dracut/anaconda-modprobe.sh | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dracut/anaconda-modprobe.sh b/dracut/anaconda-modprobe.sh
|
||||
index 97ee53bcb1..3640b4d42f 100755
|
||||
--- a/dracut/anaconda-modprobe.sh
|
||||
+++ b/dracut/anaconda-modprobe.sh
|
||||
@@ -14,11 +14,12 @@ MODULE_LIST="cramfs squashfs iscsi_tcp "
|
||||
shopt -s nullglob
|
||||
|
||||
SCSI_MODULES=/lib/modules/$KERNEL/kernel/drivers/scsi/device_handler/
|
||||
-for m in "$SCSI_MODULES"/*.ko; do
|
||||
+for m in "$SCSI_MODULES"/*.ko*; do
|
||||
# Shell spew to work around not having basename
|
||||
- # Trim the paths off the prefix, then the . suffix
|
||||
- a="${m##*/}"
|
||||
- MODULE_LIST+=" ${a%.*}"
|
||||
+ m="${m##*/}"
|
||||
+ # Handle *.ko, *.ko.zst, *.ko.gz, *.ko.xz etc.
|
||||
+ IFS='.ko' read -r -a m <<< "$m"
|
||||
+ MODULE_LIST+=" ${m[0]}"
|
||||
done
|
||||
|
||||
shopt -u nullglob
|
||||
--
|
||||
2.23.0
|
||||
@ -0,0 +1,824 @@
|
||||
From 3972b5dadcadd355d2ff25eae601bc35c336c45a Mon Sep 17 00:00:00 2001
|
||||
From: Radek Vykydal <rvykydal@redhat.com>
|
||||
Date: Thu, 29 Sep 2022 12:38:55 +0200
|
||||
Subject: [PATCH] network: use separate main conext for NM client in threads
|
||||
|
||||
Resolves: rhbz#1931389
|
||||
|
||||
Create a special NM client with separate main context for calling NM
|
||||
client from installation tasks which run in separate threads.
|
||||
|
||||
Based on a pull request by t.feng <t.feng94 at foxmail.com> who deserves
|
||||
the biggest credit, and upated with suggestions by poncovka <vponcova at
|
||||
redhat.com>
|
||||
|
||||
The created client should be used only in a limited scope as documented
|
||||
in nm_client_in_thread docstring. If we want to extend it and address
|
||||
potential issues with client instance releasing and reusing we'd need to
|
||||
follow recommendations from Thomas Haller's kind reviews:
|
||||
|
||||
<snip>
|
||||
|
||||
first of all, initializing a NMClient instance takes relatively long,
|
||||
because it makes D-Bus calls and the round trip time adds up. Btw, if
|
||||
you'd pass
|
||||
instance_flags=NM.ClientInstanceFlags.NO_AUTO_FETCH_PERMISSIONS it can
|
||||
make it faster, see here. If it's too slow, then the solution would be
|
||||
to re-use the nmclient instance or use async initialization and do stuff
|
||||
in parallel. Both is more complicated however, so not necessary unless
|
||||
we find that it's a problem.
|
||||
|
||||
What is maybe more a problem is that each GMainContext consumes at least
|
||||
one file descriptor. When you use the sync nm_client_new() method, then
|
||||
NMClient has an additional internal GMainContext, so possibly there are
|
||||
2 or more file descriptors involved. The way to "stop" NMClient is by
|
||||
unrefing it. However, with all async operations in glib, they cannot
|
||||
complete right away. That is because when NMClient gets unrefed, it will
|
||||
cancel all (internally) pending operations, but even when you cancel a
|
||||
glib operation, the callback still will be invoked with the cancellation
|
||||
error. And callbacks only get invoked by iterating/running the
|
||||
mainloop/maincontext. This means, if you have a short-running
|
||||
application (e.g. not a GUI) and a reasonable small number of NMClient
|
||||
instances, then you don't need to care. Otherwise, you unfortunately
|
||||
need to make sure that the GMainContext is still iterated just long
|
||||
enough, for all operations to be cancelled. That's slightly cumbersome,
|
||||
and you can use nm_client_get_context_busy_watcher() to find that out.
|
||||
|
||||
Btw, what you also cannot do, is having a NMClient instance alive and
|
||||
just not iterating the GMainContext anymore. NMClient will subscribe to
|
||||
D-Bus events, and those come (because GDBus has a separate worker
|
||||
thread) and will be enqueued in the GMainContext. This applies to all
|
||||
applications that register DBus signals via GDBus: you must iterate the
|
||||
context enough, so that those events get eventually processed. I think
|
||||
this does not apply to you here, but it would apply, if you try to keep
|
||||
the nmclient instance alive and reuse later.
|
||||
|
||||
</snip>
|
||||
|
||||
Reference:https://github.com/rhinstaller/anaconda/commit/3972b5dadcadd355d2ff25eae601bc35c336c45a
|
||||
Conflict:NA
|
||||
---
|
||||
pyanaconda/core/glib.py | 109 +++++++++++-
|
||||
pyanaconda/modules/network/initialization.py | 56 +++---
|
||||
pyanaconda/modules/network/installation.py | 19 +-
|
||||
pyanaconda/modules/network/network.py | 26 +--
|
||||
pyanaconda/modules/network/nm_client.py | 167 +++++++++++-------
|
||||
5 files changed, 254 insertions(+), 123 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/core/glib.py b/pyanaconda/core/glib.py
|
||||
index 03c598db43..32925384bb 100644
|
||||
--- a/pyanaconda/core/glib.py
|
||||
+++ b/pyanaconda/core/glib.py
|
||||
@@ -24,34 +24,42 @@
|
||||
|
||||
import gi
|
||||
gi.require_version("GLib", "2.0")
|
||||
+gi.require_version("Gio", "2.0")
|
||||
|
||||
from gi.repository.GLib import markup_escape_text, format_size_full, \
|
||||
timeout_add_seconds, timeout_add, idle_add, \
|
||||
io_add_watch, child_watch_add, \
|
||||
- source_remove, \
|
||||
+ source_remove, timeout_source_new, \
|
||||
spawn_close_pid, spawn_async_with_pipes, \
|
||||
MainLoop, MainContext, \
|
||||
GError, Variant, VariantType, Bytes, \
|
||||
IOCondition, IOChannel, SpawnFlags, \
|
||||
MAXUINT
|
||||
+from gi.repository.Gio import Cancellable
|
||||
+
|
||||
+from pyanaconda.anaconda_loggers import get_module_logger
|
||||
+log = get_module_logger(__name__)
|
||||
+
|
||||
|
||||
__all__ = ["create_main_loop", "create_new_context",
|
||||
"markup_escape_text", "format_size_full",
|
||||
"timeout_add_seconds", "timeout_add", "idle_add",
|
||||
"io_add_watch", "child_watch_add",
|
||||
- "source_remove",
|
||||
+ "source_remove", "timeout_source_new",
|
||||
"spawn_close_pid", "spawn_async_with_pipes",
|
||||
"GError", "Variant", "VariantType", "Bytes",
|
||||
"IOCondition", "IOChannel", "SpawnFlags",
|
||||
- "MAXUINT"]
|
||||
+ "MAXUINT", "Cancellable"]
|
||||
|
||||
|
||||
-def create_main_loop():
|
||||
+def create_main_loop(main_context=None):
|
||||
"""Create GLib main loop.
|
||||
|
||||
+ :param main_context: main context to be used for the loop
|
||||
+ :type main_context: GLib.MainContext
|
||||
:returns: GLib.MainLoop instance.
|
||||
"""
|
||||
- return MainLoop()
|
||||
+ return MainLoop(main_context)
|
||||
|
||||
|
||||
def create_new_context():
|
||||
@@ -59,3 +67,94 @@ def create_new_context():
|
||||
|
||||
:returns: GLib.MainContext."""
|
||||
return MainContext.new()
|
||||
+
|
||||
+
|
||||
+class GLibCallResult():
|
||||
+ """Result of GLib async finish callback."""
|
||||
+ def __init__(self):
|
||||
+ self.received_data = None
|
||||
+ self.error_message = ""
|
||||
+ self.timeout = False
|
||||
+
|
||||
+ @property
|
||||
+ def succeeded(self):
|
||||
+ """The async call has succeeded."""
|
||||
+ return not self.failed
|
||||
+
|
||||
+ @property
|
||||
+ def failed(self):
|
||||
+ """The async call has failed."""
|
||||
+ return bool(self.error_message) or self.timeout
|
||||
+
|
||||
+
|
||||
+def sync_call_glib(context, async_call, async_call_finish, timeout, *call_args):
|
||||
+ """Call GLib asynchronous method synchronously with timeout.
|
||||
+
|
||||
+ :param context: context for the new loop in which the method will be called
|
||||
+ :type context: GMainContext
|
||||
+ :param async_call: asynchronous GLib method to be called
|
||||
+ :type async_call: GLib method
|
||||
+ :param async_call_finish: finish method of the asynchronous call
|
||||
+ :type async_call_finish: GLib method
|
||||
+ :param timeout: timeout for the loop in seconds (0 == no timeout)
|
||||
+ :type timeout: int
|
||||
+
|
||||
+ *call_args should hold all positional arguments preceding the cancellable argument
|
||||
+ """
|
||||
+
|
||||
+ info = async_call.get_symbol()
|
||||
+ result = GLibCallResult()
|
||||
+
|
||||
+ loop = create_main_loop(context)
|
||||
+ callbacks = [loop.quit]
|
||||
+
|
||||
+ def _stop_loop():
|
||||
+ log.debug("sync_call_glib[%s]: quit", info)
|
||||
+ while callbacks:
|
||||
+ callback = callbacks.pop()
|
||||
+ callback()
|
||||
+
|
||||
+ def _cancellable_cb():
|
||||
+ log.debug("sync_call_glib[%s]: cancelled", info)
|
||||
+
|
||||
+ cancellable = Cancellable()
|
||||
+ cancellable_id = cancellable.connect(_cancellable_cb)
|
||||
+ callbacks.append(lambda: cancellable.disconnect(cancellable_id))
|
||||
+
|
||||
+ def _timeout_cb(user_data):
|
||||
+ log.debug("sync_call_glib[%s]: timeout", info)
|
||||
+ result.timeout = True
|
||||
+ cancellable.cancel()
|
||||
+ return False
|
||||
+
|
||||
+ timeout_source = timeout_source_new(int(timeout * 1000))
|
||||
+ timeout_source.set_callback(_timeout_cb)
|
||||
+ timeout_source.attach(context)
|
||||
+ callbacks.append(timeout_source.destroy)
|
||||
+
|
||||
+ def _finish_cb(source_object, async_result):
|
||||
+ log.debug("sync_call_glib[%s]: call %s",
|
||||
+ info,
|
||||
+ async_call_finish.get_symbol())
|
||||
+ try:
|
||||
+ result.received_data = async_call_finish(async_result)
|
||||
+ except Exception as e: # pylint: disable=broad-except
|
||||
+ result.error_message = str(e)
|
||||
+ finally:
|
||||
+ _stop_loop()
|
||||
+
|
||||
+ context.push_thread_default()
|
||||
+
|
||||
+ log.debug("sync_call_glib[%s]: call", info)
|
||||
+ try:
|
||||
+ async_call(
|
||||
+ *call_args,
|
||||
+ cancellable=cancellable,
|
||||
+ callback=_finish_cb
|
||||
+ )
|
||||
+ loop.run()
|
||||
+ finally:
|
||||
+ _stop_loop()
|
||||
+ context.pop_thread_default()
|
||||
+
|
||||
+ return result
|
||||
diff --git a/pyanaconda/modules/network/initialization.py b/pyanaconda/modules/network/initialization.py
|
||||
index c7f0ba4cf8..bf1ffd12af 100644
|
||||
--- a/pyanaconda/modules/network/initialization.py
|
||||
+++ b/pyanaconda/modules/network/initialization.py
|
||||
@@ -25,7 +25,7 @@ from pyanaconda.modules.network.network_interface import NetworkInitializationTa
|
||||
from pyanaconda.modules.network.nm_client import get_device_name_from_network_data, \
|
||||
update_connection_from_ksdata, add_connection_from_ksdata, bound_hwaddr_of_device, \
|
||||
update_connection_values, commit_changes_with_autoconnection_blocked, \
|
||||
- get_config_file_connection_of_device, clone_connection_sync
|
||||
+ get_config_file_connection_of_device, clone_connection_sync, nm_client_in_thread
|
||||
from pyanaconda.modules.network.device_configuration import supported_wired_device_types, \
|
||||
virtual_device_types
|
||||
from pyanaconda.modules.network.utils import guard_by_system_configuration
|
||||
@@ -40,11 +40,9 @@ from gi.repository import NM
|
||||
class ApplyKickstartTask(Task):
|
||||
"""Task for application of kickstart network configuration."""
|
||||
|
||||
- def __init__(self, nm_client, network_data, supported_devices, bootif, ifname_option_values):
|
||||
+ def __init__(self, network_data, supported_devices, bootif, ifname_option_values):
|
||||
"""Create a new task.
|
||||
|
||||
- :param nm_client: NetworkManager client used as configuration backend
|
||||
- :type nm_client: NM.Client
|
||||
:param network_data: kickstart network data to be applied
|
||||
:type: list(NetworkData)
|
||||
:param supported_devices: list of names of supported network devices
|
||||
@@ -55,7 +53,6 @@ class ApplyKickstartTask(Task):
|
||||
:type ifname_option_values: list(str)
|
||||
"""
|
||||
super().__init__()
|
||||
- self._nm_client = nm_client
|
||||
self._network_data = network_data
|
||||
self._supported_devices = supported_devices
|
||||
self._bootif = bootif
|
||||
@@ -76,13 +73,17 @@ class ApplyKickstartTask(Task):
|
||||
:returns: names of devices to which kickstart was applied
|
||||
:rtype: list(str)
|
||||
"""
|
||||
+ with nm_client_in_thread() as nm_client:
|
||||
+ return self._run(nm_client)
|
||||
+
|
||||
+ def _run(self, nm_client):
|
||||
applied_devices = []
|
||||
|
||||
if not self._network_data:
|
||||
log.debug("%s: No kickstart data.", self.name)
|
||||
return applied_devices
|
||||
|
||||
- if not self._nm_client:
|
||||
+ if not nm_client:
|
||||
log.debug("%s: No NetworkManager available.", self.name)
|
||||
return applied_devices
|
||||
|
||||
@@ -92,7 +93,7 @@ class ApplyKickstartTask(Task):
|
||||
log.info("%s: Wireless devices configuration is not supported.", self.name)
|
||||
continue
|
||||
|
||||
- device_name = get_device_name_from_network_data(self._nm_client,
|
||||
+ device_name = get_device_name_from_network_data(nm_client,
|
||||
network_data,
|
||||
self._supported_devices,
|
||||
self._bootif)
|
||||
@@ -102,28 +103,28 @@ class ApplyKickstartTask(Task):
|
||||
|
||||
applied_devices.append(device_name)
|
||||
|
||||
- connection = self._find_initramfs_connection_of_iface(device_name)
|
||||
+ connection = self._find_initramfs_connection_of_iface(nm_client, device_name)
|
||||
|
||||
if connection:
|
||||
# if the device was already configured in initramfs update the settings
|
||||
log.debug("%s: updating connection %s of device %s",
|
||||
self.name, connection.get_uuid(), device_name)
|
||||
update_connection_from_ksdata(
|
||||
- self._nm_client,
|
||||
+ nm_client,
|
||||
connection,
|
||||
network_data,
|
||||
device_name,
|
||||
ifname_option_values=self._ifname_option_values
|
||||
)
|
||||
if network_data.activate:
|
||||
- device = self._nm_client.get_device_by_iface(device_name)
|
||||
- self._nm_client.activate_connection_async(connection, device, None, None)
|
||||
+ device = nm_client.get_device_by_iface(device_name)
|
||||
+ nm_client.activate_connection_async(connection, device, None, None)
|
||||
log.debug("%s: activating updated connection %s with device %s",
|
||||
self.name, connection.get_uuid(), device_name)
|
||||
else:
|
||||
log.debug("%s: adding connection for %s", self.name, device_name)
|
||||
add_connection_from_ksdata(
|
||||
- self._nm_client,
|
||||
+ nm_client,
|
||||
network_data,
|
||||
device_name,
|
||||
activate=network_data.activate,
|
||||
@@ -132,8 +133,8 @@ class ApplyKickstartTask(Task):
|
||||
|
||||
return applied_devices
|
||||
|
||||
- def _find_initramfs_connection_of_iface(self, iface):
|
||||
- device = self._nm_client.get_device_by_iface(iface)
|
||||
+ def _find_initramfs_connection_of_iface(self, nm_client, iface):
|
||||
+ device = nm_client.get_device_by_iface(iface)
|
||||
if device:
|
||||
cons = device.get_available_connections()
|
||||
for con in cons:
|
||||
@@ -145,18 +146,15 @@ class ApplyKickstartTask(Task):
|
||||
class DumpMissingConfigFilesTask(Task):
|
||||
"""Task for dumping of missing config files."""
|
||||
|
||||
- def __init__(self, nm_client, default_network_data, ifname_option_values):
|
||||
+ def __init__(self, default_network_data, ifname_option_values):
|
||||
"""Create a new task.
|
||||
|
||||
- :param nm_client: NetworkManager client used as configuration backend
|
||||
- :type nm_client: NM.Client
|
||||
:param default_network_data: kickstart network data of default device configuration
|
||||
:type default_network_data: NetworkData
|
||||
:param ifname_option_values: list of ifname boot option values
|
||||
:type ifname_option_values: list(str)
|
||||
"""
|
||||
super().__init__()
|
||||
- self._nm_client = nm_client
|
||||
self._default_network_data = default_network_data
|
||||
self._ifname_option_values = ifname_option_values
|
||||
|
||||
@@ -186,7 +184,7 @@ class DumpMissingConfigFilesTask(Task):
|
||||
return con
|
||||
return None
|
||||
|
||||
- def _update_connection(self, con, iface):
|
||||
+ def _update_connection(self, nm_client, con, iface):
|
||||
log.debug("%s: updating id and binding (interface-name) of connection %s for %s",
|
||||
self.name, con.get_uuid(), iface)
|
||||
s_con = con.get_setting_connection()
|
||||
@@ -196,7 +194,7 @@ class DumpMissingConfigFilesTask(Task):
|
||||
if s_wired:
|
||||
# By default connections are bound to interface name
|
||||
s_wired.set_property(NM.SETTING_WIRED_MAC_ADDRESS, None)
|
||||
- bound_mac = bound_hwaddr_of_device(self._nm_client, iface, self._ifname_option_values)
|
||||
+ bound_mac = bound_hwaddr_of_device(nm_client, iface, self._ifname_option_values)
|
||||
if bound_mac:
|
||||
s_wired.set_property(NM.SETTING_WIRED_MAC_ADDRESS, bound_mac)
|
||||
log.debug("%s: iface %s bound to mac address %s by ifname boot option",
|
||||
@@ -216,19 +214,23 @@ class DumpMissingConfigFilesTask(Task):
|
||||
:returns: names of devices for which config file was created
|
||||
:rtype: list(str)
|
||||
"""
|
||||
+ with nm_client_in_thread() as nm_client:
|
||||
+ return self._run(nm_client)
|
||||
+
|
||||
+ def _run(self, nm_client):
|
||||
new_configs = []
|
||||
|
||||
- if not self._nm_client:
|
||||
+ if not nm_client:
|
||||
log.debug("%s: No NetworkManager available.", self.name)
|
||||
return new_configs
|
||||
|
||||
dumped_device_types = supported_wired_device_types + virtual_device_types
|
||||
- for device in self._nm_client.get_devices():
|
||||
+ for device in nm_client.get_devices():
|
||||
if device.get_device_type() not in dumped_device_types:
|
||||
continue
|
||||
|
||||
iface = device.get_iface()
|
||||
- if get_config_file_connection_of_device(self._nm_client, iface):
|
||||
+ if get_config_file_connection_of_device(nm_client, iface):
|
||||
continue
|
||||
|
||||
cons = device.get_available_connections()
|
||||
@@ -259,10 +261,10 @@ class DumpMissingConfigFilesTask(Task):
|
||||
# Try to clone the persistent connection for the device
|
||||
# from the connection which should be a generic (not bound
|
||||
# to iface) connection created by NM in initramfs
|
||||
- con = clone_connection_sync(self._nm_client, cons[0], con_id=iface)
|
||||
+ con = clone_connection_sync(nm_client, cons[0], con_id=iface)
|
||||
|
||||
if con:
|
||||
- self._update_connection(con, iface)
|
||||
+ self._update_connection(nm_client, con, iface)
|
||||
# Update some values of connection generated in initramfs so it
|
||||
# can be used as persistent configuration.
|
||||
if has_initramfs_con:
|
||||
@@ -285,7 +287,7 @@ class DumpMissingConfigFilesTask(Task):
|
||||
)
|
||||
log.debug("%s: dumping connection %s to config file for %s",
|
||||
self.name, con.get_uuid(), iface)
|
||||
- commit_changes_with_autoconnection_blocked(con)
|
||||
+ commit_changes_with_autoconnection_blocked(con, nm_client)
|
||||
else:
|
||||
log.debug("%s: none of the connections can be dumped as persistent",
|
||||
self.name)
|
||||
@@ -298,7 +300,7 @@ class DumpMissingConfigFilesTask(Task):
|
||||
if has_initramfs_con:
|
||||
network_data.onboot = True
|
||||
add_connection_from_ksdata(
|
||||
- self._nm_client,
|
||||
+ nm_client,
|
||||
network_data,
|
||||
iface,
|
||||
activate=False,
|
||||
diff --git a/pyanaconda/modules/network/installation.py b/pyanaconda/modules/network/installation.py
|
||||
index 3ac65e0df0..d91eb51ae7 100644
|
||||
--- a/pyanaconda/modules/network/installation.py
|
||||
+++ b/pyanaconda/modules/network/installation.py
|
||||
@@ -23,7 +23,7 @@ from pyanaconda.modules.common.errors.installation import NetworkInstallationErr
|
||||
from pyanaconda.modules.common.task import Task
|
||||
from pyanaconda.anaconda_loggers import get_module_logger
|
||||
from pyanaconda.modules.network.nm_client import update_connection_values, \
|
||||
- commit_changes_with_autoconnection_blocked
|
||||
+ commit_changes_with_autoconnection_blocked, nm_client_in_thread
|
||||
from pyanaconda.modules.network.utils import guard_by_system_configuration
|
||||
from pyanaconda.modules.network.nm_client import get_config_file_connection_of_device
|
||||
from pyanaconda.modules.network.config_file import IFCFG_DIR, KEYFILE_DIR
|
||||
@@ -281,16 +281,13 @@ Name={}
|
||||
class ConfigureActivationOnBootTask(Task):
|
||||
"""Task for configuration of automatic activation of devices on boot"""
|
||||
|
||||
- def __init__(self, nm_client, onboot_ifaces):
|
||||
+ def __init__(self, onboot_ifaces):
|
||||
"""Create a new task.
|
||||
|
||||
- :param nm_client: NetworkManager client used as configuration backend
|
||||
- :type nm_client: NM.Client
|
||||
:param onboot_ifaces: interfaces that should be autoactivated on boot
|
||||
:type onboot_ifaces: list(str)
|
||||
"""
|
||||
super().__init__()
|
||||
- self._nm_client = nm_client
|
||||
self._onboot_ifaces = onboot_ifaces
|
||||
|
||||
@property
|
||||
@@ -299,18 +296,22 @@ class ConfigureActivationOnBootTask(Task):
|
||||
|
||||
@guard_by_system_configuration(return_value=None)
|
||||
def run(self):
|
||||
- if not self._nm_client:
|
||||
+ with nm_client_in_thread() as nm_client:
|
||||
+ return self._run(nm_client)
|
||||
+
|
||||
+ def _run(self, nm_client):
|
||||
+ if not nm_client:
|
||||
log.debug("%s: No NetworkManager available.", self.name)
|
||||
return None
|
||||
|
||||
for iface in self._onboot_ifaces:
|
||||
- con_uuid = get_config_file_connection_of_device(self._nm_client, iface)
|
||||
+ con_uuid = get_config_file_connection_of_device(nm_client, iface)
|
||||
if con_uuid:
|
||||
- con = self._nm_client.get_connection_by_uuid(con_uuid)
|
||||
+ con = nm_client.get_connection_by_uuid(con_uuid)
|
||||
update_connection_values(
|
||||
con,
|
||||
[("connection", NM.SETTING_CONNECTION_AUTOCONNECT, True)]
|
||||
)
|
||||
- commit_changes_with_autoconnection_blocked(con)
|
||||
+ commit_changes_with_autoconnection_blocked(con, nm_client)
|
||||
else:
|
||||
log.warning("Configure ONBOOT: can't find config for %s", iface)
|
||||
diff --git a/pyanaconda/modules/network/network.py b/pyanaconda/modules/network/network.py
|
||||
index 445c9d8b46..a905ee31d6 100644
|
||||
--- a/pyanaconda/modules/network/network.py
|
||||
+++ b/pyanaconda/modules/network/network.py
|
||||
@@ -23,7 +23,7 @@ from pyanaconda.core.async_utils import run_in_loop
|
||||
from pyanaconda.core.configuration.anaconda import conf
|
||||
from pyanaconda.core.configuration.network import NetworkOnBoot
|
||||
from pyanaconda.core.kernel import kernel_arguments
|
||||
-from pyanaconda.core.dbus import DBus, SystemBus
|
||||
+from pyanaconda.core.dbus import DBus
|
||||
from pyanaconda.core.signal import Signal
|
||||
from pyanaconda.modules.common.base import KickstartService
|
||||
from pyanaconda.modules.common.containers import TaskContainer
|
||||
@@ -37,7 +37,7 @@ from pyanaconda.modules.network.firewall import FirewallModule
|
||||
from pyanaconda.modules.network.device_configuration import DeviceConfigurations, \
|
||||
supported_device_types, supported_wired_device_types
|
||||
from pyanaconda.modules.network.nm_client import devices_ignore_ipv6, get_connections_dump, \
|
||||
- get_dracut_arguments_from_connection, get_kickstart_network_data
|
||||
+ get_dracut_arguments_from_connection, get_kickstart_network_data, get_new_nm_client
|
||||
from pyanaconda.modules.network.config_file import get_config_files_content, \
|
||||
is_config_file_for_system
|
||||
from pyanaconda.modules.network.installation import NetworkInstallationTask, \
|
||||
@@ -70,17 +70,12 @@ class NetworkService(KickstartService):
|
||||
self._hostname_service_proxy = self._get_hostname_proxy()
|
||||
|
||||
self.connected_changed = Signal()
|
||||
- self.nm_client = None
|
||||
# TODO fallback solution - use Gio/GNetworkMonitor ?
|
||||
- if SystemBus.check_connection():
|
||||
- nm_client = NM.Client.new(None)
|
||||
- if nm_client.get_nm_running():
|
||||
- self.nm_client = nm_client
|
||||
- self.nm_client.connect("notify::%s" % NM.CLIENT_STATE, self._nm_state_changed)
|
||||
- initial_state = self.nm_client.get_state()
|
||||
- self.set_connected(self._nm_state_connected(initial_state))
|
||||
- else:
|
||||
- log.debug("NetworkManager is not running.")
|
||||
+ self.nm_client = get_new_nm_client()
|
||||
+ if self.nm_client:
|
||||
+ self.nm_client.connect("notify::%s" % NM.CLIENT_STATE, self._nm_state_changed)
|
||||
+ initial_state = self.nm_client.get_state()
|
||||
+ self.set_connected(self._nm_state_connected(initial_state))
|
||||
|
||||
self._original_network_data = []
|
||||
self._device_configurations = None
|
||||
@@ -393,7 +388,6 @@ class NetworkService(KickstartService):
|
||||
all_onboot_ifaces = list(set(onboot_ifaces + onboot_ifaces_by_policy))
|
||||
|
||||
task = ConfigureActivationOnBootTask(
|
||||
- self.nm_client,
|
||||
all_onboot_ifaces
|
||||
)
|
||||
task.succeeded_signal.connect(lambda: self.log_task_result(task))
|
||||
@@ -616,8 +610,7 @@ class NetworkService(KickstartService):
|
||||
:returns: a task applying the kickstart
|
||||
"""
|
||||
supported_devices = [dev_info.device_name for dev_info in self.get_supported_devices()]
|
||||
- task = ApplyKickstartTask(self.nm_client,
|
||||
- self._original_network_data,
|
||||
+ task = ApplyKickstartTask(self._original_network_data,
|
||||
supported_devices,
|
||||
self.bootif,
|
||||
self.ifname_option_values)
|
||||
@@ -645,8 +638,7 @@ class NetworkService(KickstartService):
|
||||
"""
|
||||
data = self.get_kickstart_handler()
|
||||
default_network_data = data.NetworkData(onboot=False, ipv6="auto")
|
||||
- task = DumpMissingConfigFilesTask(self.nm_client,
|
||||
- default_network_data,
|
||||
+ task = DumpMissingConfigFilesTask(default_network_data,
|
||||
self.ifname_option_values)
|
||||
task.succeeded_signal.connect(lambda: self.log_task_result(task, check_result=True))
|
||||
return task
|
||||
diff --git a/pyanaconda/modules/network/nm_client.py b/pyanaconda/modules/network/nm_client.py
|
||||
index 3cc28ec48e..421ef1e0d9 100644
|
||||
--- a/pyanaconda/modules/network/nm_client.py
|
||||
+++ b/pyanaconda/modules/network/nm_client.py
|
||||
@@ -21,18 +21,20 @@
|
||||
import gi
|
||||
gi.require_version("NM", "1.0")
|
||||
from gi.repository import NM
|
||||
+from contextlib import contextmanager
|
||||
|
||||
import socket
|
||||
-from queue import Queue, Empty
|
||||
from pykickstart.constants import BIND_TO_MAC
|
||||
+from pyanaconda.core.glib import create_new_context, GError, sync_call_glib
|
||||
from pyanaconda.modules.network.constants import NM_CONNECTION_UUID_LENGTH, \
|
||||
- CONNECTION_ACTIVATION_TIMEOUT, NM_CONNECTION_TYPE_WIFI, NM_CONNECTION_TYPE_ETHERNET, \
|
||||
+ CONNECTION_ADDING_TIMEOUT, NM_CONNECTION_TYPE_WIFI, NM_CONNECTION_TYPE_ETHERNET, \
|
||||
NM_CONNECTION_TYPE_VLAN, NM_CONNECTION_TYPE_BOND, NM_CONNECTION_TYPE_TEAM, \
|
||||
- NM_CONNECTION_TYPE_BRIDGE, NM_CONNECTION_TYPE_INFINIBAND, CONNECTION_ADDING_TIMEOUT
|
||||
+ NM_CONNECTION_TYPE_BRIDGE, NM_CONNECTION_TYPE_INFINIBAND
|
||||
from pyanaconda.modules.network.kickstart import default_ks_vlan_interface_name
|
||||
from pyanaconda.modules.network.utils import is_s390, get_s390_settings, netmask2prefix, \
|
||||
prefix2netmask
|
||||
from pyanaconda.modules.network.config_file import is_config_file_for_system
|
||||
+from pyanaconda.core.dbus import SystemBus
|
||||
|
||||
from pyanaconda.anaconda_loggers import get_module_logger
|
||||
log = get_module_logger(__name__)
|
||||
@@ -51,6 +53,51 @@ NM_BRIDGE_DUMPED_SETTINGS_DEFAULTS = {
|
||||
}
|
||||
|
||||
|
||||
+@contextmanager
|
||||
+def nm_client_in_thread():
|
||||
+ """Create NM Client with new GMainContext to be run in thread.
|
||||
+
|
||||
+ Expected to be used only in installer environment for a few
|
||||
+ one-shot isolated network configuration tasks.
|
||||
+ Destroying of the created NM Client instance and release of
|
||||
+ related resources is not implemented.
|
||||
+
|
||||
+ For more information see NetworkManager example examples/python/gi/gmaincontext.py
|
||||
+ """
|
||||
+ mainctx = create_new_context()
|
||||
+ mainctx.push_thread_default()
|
||||
+
|
||||
+ try:
|
||||
+ yield get_new_nm_client()
|
||||
+ finally:
|
||||
+ mainctx.pop_thread_default()
|
||||
+
|
||||
+
|
||||
+def get_new_nm_client():
|
||||
+ """Get new instance of NMClient.
|
||||
+
|
||||
+ :returns: an instance of NetworkManager NMClient or None if system bus
|
||||
+ is not available or NM is not running
|
||||
+ :rtype: NM.NMClient
|
||||
+ """
|
||||
+ if not SystemBus.check_connection():
|
||||
+ log.debug("get new NM Client failed: SystemBus connection check failed.")
|
||||
+ return None
|
||||
+
|
||||
+ try:
|
||||
+ nm_client = NM.Client.new(None)
|
||||
+ except GError as e:
|
||||
+ log.debug("get new NM Client constructor failed: %s", e)
|
||||
+ return None
|
||||
+
|
||||
+ if not nm_client.get_nm_running():
|
||||
+ log.debug("get new NM Client failed: NetworkManager is not running.")
|
||||
+ return None
|
||||
+
|
||||
+ log.debug("get new NM Client succeeded.")
|
||||
+ return nm_client
|
||||
+
|
||||
+
|
||||
def get_iface_from_connection(nm_client, uuid):
|
||||
"""Get the name of device that would be used for the connection.
|
||||
|
||||
@@ -268,7 +315,7 @@ def _add_existing_virtual_device_to_bridge(nm_client, device_name, bridge_spec):
|
||||
bridge_spec),
|
||||
]
|
||||
)
|
||||
- commit_changes_with_autoconnection_blocked(port_connection)
|
||||
+ commit_changes_with_autoconnection_blocked(port_connection, nm_client)
|
||||
return port_connection.get_uuid()
|
||||
|
||||
|
||||
@@ -532,7 +579,7 @@ def add_connection_from_ksdata(nm_client, network_data, device_name, activate=Fa
|
||||
connection.to_dbus(NM.ConnectionSerializationFlags.NO_SECRETS))
|
||||
added_connection = add_connection_sync(
|
||||
nm_client,
|
||||
- connection,
|
||||
+ connection
|
||||
)
|
||||
|
||||
if not added_connection:
|
||||
@@ -557,37 +604,39 @@ def add_connection_from_ksdata(nm_client, network_data, device_name, activate=Fa
|
||||
def add_connection_sync(nm_client, connection):
|
||||
"""Add a connection synchronously and optionally activate asynchronously.
|
||||
|
||||
+ Synchronous run is implemented by running a blocking GMainLoop with
|
||||
+ GMainContext belonging to the nm_client created for the calling Task.
|
||||
+
|
||||
+ :param nm_client: NetoworkManager client
|
||||
+ :type nm_client: NM.NMClient
|
||||
:param connection: connection to be added
|
||||
:type connection: NM.SimpleConnection
|
||||
:return: added connection or None on timeout
|
||||
:rtype: NM.RemoteConnection
|
||||
"""
|
||||
- sync_queue = Queue()
|
||||
-
|
||||
- def finish_callback(nm_client, result, sync_queue):
|
||||
- con, result = nm_client.add_connection2_finish(result)
|
||||
- log.debug("connection %s added:\n%s", con.get_uuid(),
|
||||
- con.to_dbus(NM.ConnectionSerializationFlags.NO_SECRETS))
|
||||
- sync_queue.put(con)
|
||||
-
|
||||
- nm_client.add_connection2(
|
||||
+ result = sync_call_glib(
|
||||
+ nm_client.get_main_context(),
|
||||
+ nm_client.add_connection2,
|
||||
+ nm_client.add_connection2_finish,
|
||||
+ CONNECTION_ADDING_TIMEOUT,
|
||||
connection.to_dbus(NM.ConnectionSerializationFlags.ALL),
|
||||
(NM.SettingsAddConnection2Flags.TO_DISK |
|
||||
NM.SettingsAddConnection2Flags.BLOCK_AUTOCONNECT),
|
||||
None,
|
||||
- False,
|
||||
- None,
|
||||
- finish_callback,
|
||||
- sync_queue
|
||||
+ False
|
||||
)
|
||||
|
||||
- try:
|
||||
- ret = sync_queue.get(timeout=CONNECTION_ADDING_TIMEOUT)
|
||||
- except Empty:
|
||||
- log.error("Adding of connection %s timed out.", connection.get_uuid())
|
||||
- ret = None
|
||||
+ if result.failed:
|
||||
+ log.error("adding of a connection %s failed: %s",
|
||||
+ connection.get_uuid(),
|
||||
+ result.error_message)
|
||||
+ return None
|
||||
+
|
||||
+ con, _res = result.received_data
|
||||
+ log.debug("connection %s added:\n%s", connection.get_uuid(),
|
||||
+ connection.to_dbus(NM.ConnectionSerializationFlags.NO_SECRETS))
|
||||
|
||||
- return ret
|
||||
+ return con
|
||||
|
||||
|
||||
def create_port_connection(port_type, port_idx, port, controller, autoconnect, settings=None):
|
||||
@@ -713,7 +762,7 @@ def update_connection_from_ksdata(nm_client, connection, network_data, device_na
|
||||
else:
|
||||
bind_connection(nm_client, connection, network_data.bindto, device_name)
|
||||
|
||||
- commit_changes_with_autoconnection_blocked(connection)
|
||||
+ commit_changes_with_autoconnection_blocked(connection, nm_client)
|
||||
|
||||
log.debug("updated connection %s:\n%s", connection.get_uuid(),
|
||||
connection.to_dbus(NM.ConnectionSerializationFlags.NO_SECRETS))
|
||||
@@ -1013,42 +1062,47 @@ def get_connections_dump(nm_client):
|
||||
return "\n".join(con_dumps)
|
||||
|
||||
|
||||
-def commit_changes_with_autoconnection_blocked(connection, save_to_disk=True):
|
||||
+def commit_changes_with_autoconnection_blocked(connection, nm_client, save_to_disk=True):
|
||||
"""Implementation of NM CommitChanges() method with blocked autoconnection.
|
||||
|
||||
- Update2() API is used to implement the functionality (called synchronously).
|
||||
-
|
||||
+ Update2() API is used to implement the functionality.
|
||||
Prevents autoactivation of the connection on its update which would happen
|
||||
with CommitChanges if "autoconnect" is set True.
|
||||
|
||||
+ Synchronous run is implemented by running a blocking GMainLoop with
|
||||
+ GMainContext belonging to the nm_client created for the calling Task.
|
||||
+
|
||||
:param connection: NetworkManager connection
|
||||
:type connection: NM.RemoteConnection
|
||||
+ :param nm_client: NetoworkManager client
|
||||
+ :type nm_client: NM.NMClient
|
||||
:param save_to_disk: should the changes be written also to disk?
|
||||
:type save_to_disk: bool
|
||||
:return: on success result of the Update2() call, None of failure
|
||||
:rtype: GVariant of type "a{sv}" or None
|
||||
"""
|
||||
- sync_queue = Queue()
|
||||
-
|
||||
- def finish_callback(connection, result, sync_queue):
|
||||
- ret = connection.update2_finish(result)
|
||||
- sync_queue.put(ret)
|
||||
-
|
||||
flags = NM.SettingsUpdate2Flags.BLOCK_AUTOCONNECT
|
||||
if save_to_disk:
|
||||
flags |= NM.SettingsUpdate2Flags.TO_DISK
|
||||
-
|
||||
con2 = NM.SimpleConnection.new_clone(connection)
|
||||
- connection.update2(
|
||||
+
|
||||
+ result = sync_call_glib(
|
||||
+ nm_client.get_main_context(),
|
||||
+ connection.update2,
|
||||
+ connection.update2_finish,
|
||||
+ CONNECTION_ADDING_TIMEOUT,
|
||||
con2.to_dbus(NM.ConnectionSerializationFlags.ALL),
|
||||
flags,
|
||||
- None,
|
||||
- None,
|
||||
- finish_callback,
|
||||
- sync_queue
|
||||
+ None
|
||||
)
|
||||
|
||||
- return sync_queue.get()
|
||||
+ if result.failed:
|
||||
+ log.error("comitting changes of connection %s failed: %s",
|
||||
+ connection.get_uuid(),
|
||||
+ result.error_message)
|
||||
+ return None
|
||||
+
|
||||
+ return result.received_data
|
||||
|
||||
|
||||
def clone_connection_sync(nm_client, connection, con_id=None, uuid=None):
|
||||
@@ -1063,36 +1117,19 @@ def clone_connection_sync(nm_client, connection, con_id=None, uuid=None):
|
||||
:return: NetworkManager connection or None on timeout
|
||||
:rtype: NM.RemoteConnection
|
||||
"""
|
||||
- sync_queue = Queue()
|
||||
-
|
||||
- def finish_callback(nm_client, result, sync_queue):
|
||||
- con, result = nm_client.add_connection2_finish(result)
|
||||
- log.debug("connection %s cloned:\n%s", con.get_uuid(),
|
||||
- con.to_dbus(NM.ConnectionSerializationFlags.NO_SECRETS))
|
||||
- sync_queue.put(con)
|
||||
-
|
||||
cloned_connection = NM.SimpleConnection.new_clone(connection)
|
||||
s_con = cloned_connection.get_setting_connection()
|
||||
s_con.props.uuid = uuid or NM.utils_uuid_generate()
|
||||
s_con.props.id = con_id or "{}-clone".format(connection.get_id())
|
||||
- nm_client.add_connection2(
|
||||
- cloned_connection.to_dbus(NM.ConnectionSerializationFlags.ALL),
|
||||
- (NM.SettingsAddConnection2Flags.TO_DISK |
|
||||
- NM.SettingsAddConnection2Flags.BLOCK_AUTOCONNECT),
|
||||
- None,
|
||||
- False,
|
||||
- None,
|
||||
- finish_callback,
|
||||
- sync_queue
|
||||
- )
|
||||
|
||||
- try:
|
||||
- ret = sync_queue.get(timeout=CONNECTION_ACTIVATION_TIMEOUT)
|
||||
- except Empty:
|
||||
- log.error("Cloning of a connection timed out.")
|
||||
- ret = None
|
||||
+ log.debug("cloning connection %s", connection.get_uuid())
|
||||
+ added_connection = add_connection_sync(nm_client, cloned_connection)
|
||||
|
||||
- return ret
|
||||
+ if added_connection:
|
||||
+ log.debug("connection was cloned into %s", added_connection.get_uuid())
|
||||
+ else:
|
||||
+ log.debug("connection cloning failed")
|
||||
+ return added_connection
|
||||
|
||||
|
||||
def get_dracut_arguments_from_connection(nm_client, connection, iface, target_ip,
|
||||
--
|
||||
2.23.0
|
||||
@ -11,9 +11,9 @@ diff --git a/pyanaconda/modules/network/initialization.py b/pyanaconda/modules/n
|
||||
index c7f0ba4..85a1da7 100644
|
||||
--- a/pyanaconda/modules/network/initialization.py
|
||||
+++ b/pyanaconda/modules/network/initialization.py
|
||||
@@ -135,6 +135,9 @@ class ApplyKickstartTask(Task):
|
||||
def _find_initramfs_connection_of_iface(self, iface):
|
||||
device = self._nm_client.get_device_by_iface(iface)
|
||||
@@ -136,6 +136,9 @@ class ApplyKickstartTask(Task):
|
||||
def _find_initramfs_connection_of_iface(self, nm_client, iface):
|
||||
device = nm_client.get_device_by_iface(iface)
|
||||
if device:
|
||||
+ active_connection = device.get_active_connection()
|
||||
+ if active_connection:
|
||||
|
||||
@ -0,0 +1,104 @@
|
||||
From d5d6b1498db9f9e3378c11421caa523556c04752 Mon Sep 17 00:00:00 2001
|
||||
From: sun_hai_10 <sunhai10@huawei.com>
|
||||
Date: Tue, 28 Mar 2023 14:22:39 +0800
|
||||
Subject: [PATCH] revert Unify GRUB configuration file location across all platforms
|
||||
Reference:https://github.com/rhinstaller/anaconda/commit/15c3b2044367d375db6739e8b8f419ef3e17cae7
|
||||
---
|
||||
pyanaconda/modules/storage/bootloader/efi.py | 38 +------------------
|
||||
.../modules/storage/bootloader/utils.py | 8 +++-
|
||||
2 files changed, 9 insertions(+), 37 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/bootloader/efi.py b/pyanaconda/modules/storage/bootloader/efi.py
|
||||
index 1b47e24..6135699 100644
|
||||
--- a/pyanaconda/modules/storage/bootloader/efi.py
|
||||
+++ b/pyanaconda/modules/storage/bootloader/efi.py
|
||||
@@ -35,11 +35,7 @@ class EFIBase(object):
|
||||
"""A base class for EFI-based boot loaders."""
|
||||
|
||||
@property
|
||||
- def efi_config_dir(self):
|
||||
- return "/boot/" + self._efi_config_dir
|
||||
-
|
||||
- @property
|
||||
- def _efi_config_dir(self):
|
||||
+ def _config_dir(self):
|
||||
return "efi/EFI/{}".format(conf.bootloader.efi_dir)
|
||||
|
||||
def efibootmgr(self, *args, **kwargs):
|
||||
@@ -62,7 +58,7 @@ class EFIBase(object):
|
||||
|
||||
@property
|
||||
def efi_dir_as_efifs_dir(self):
|
||||
- ret = self._efi_config_dir.replace('efi/', '')
|
||||
+ ret = self._config_dir.replace('efi/', '')
|
||||
return "\\" + ret.replace('/', '\\')
|
||||
|
||||
def _add_single_efi_boot_target(self, partition):
|
||||
@@ -164,36 +160,6 @@ class EFIGRUB(EFIBase, GRUB2):
|
||||
return self._packages32 + self._packages_common
|
||||
return self._packages64 + self._packages_common
|
||||
|
||||
- @property
|
||||
- def efi_config_file(self):
|
||||
- """ Full path to EFI configuration file. """
|
||||
- return "%s/%s" % (self.efi_config_dir, self._config_file)
|
||||
-
|
||||
- def write_config(self):
|
||||
- config_path = "%s%s" % (conf.target.system_root, self.efi_config_file)
|
||||
-
|
||||
- with open(config_path, "w") as fd:
|
||||
- grub_dir = self.config_dir
|
||||
- if self.stage2_device.format.type != "btrfs":
|
||||
- fs_uuid = self.stage2_device.format.uuid
|
||||
- else:
|
||||
- fs_uuid = self.stage2_device.format.vol_uuid
|
||||
-
|
||||
- if fs_uuid is None:
|
||||
- raise BootLoaderError("Could not get stage2 filesystem UUID")
|
||||
-
|
||||
- grub_dir = util.execWithCapture("grub2-mkrelpath", [grub_dir],
|
||||
- root=conf.target.system_root)
|
||||
- if not grub_dir:
|
||||
- raise BootLoaderError("Could not get GRUB directory path")
|
||||
-
|
||||
- fd.write("search --no-floppy --fs-uuid --set=dev %s\n" % fs_uuid)
|
||||
- fd.write("set prefix=($dev)%s\n" % grub_dir)
|
||||
- fd.write("export $prefix\n")
|
||||
- fd.write("configfile $prefix/grub.cfg\n")
|
||||
-
|
||||
- super().write_config()
|
||||
-
|
||||
|
||||
class Aarch64EFIGRUB(EFIGRUB):
|
||||
_serial_consoles = ["ttyAMA", "ttyS"]
|
||||
diff --git a/pyanaconda/modules/storage/bootloader/utils.py b/pyanaconda/modules/storage/bootloader/utils.py
|
||||
index 27fc2a0..84e45b6 100644
|
||||
--- a/pyanaconda/modules/storage/bootloader/utils.py
|
||||
+++ b/pyanaconda/modules/storage/bootloader/utils.py
|
||||
@@ -19,6 +19,7 @@ import os
|
||||
from glob import glob
|
||||
|
||||
from pyanaconda.modules.common.errors.installation import BootloaderInstallationError
|
||||
+from pyanaconda.modules.storage.bootloader.efi import EFIBase
|
||||
from pyanaconda.modules.storage.bootloader.image import LinuxBootLoaderImage
|
||||
from pyanaconda.core.configuration.anaconda import conf
|
||||
from pyanaconda.core.util import execWithRedirect
|
||||
@@ -244,9 +245,14 @@ def create_bls_entries(sysroot, storage, kernel_versions):
|
||||
# Update the bootloader configuration to make sure that the BLS
|
||||
# entries will have the correct kernel cmdline and not the value
|
||||
# taken from /proc/cmdline, that is used to boot the live image.
|
||||
+ if isinstance(storage.bootloader, EFIBase):
|
||||
+ grub_cfg_path = "/etc/grub2-efi.cfg"
|
||||
+ else:
|
||||
+ grub_cfg_path = "/etc/grub2.cfg"
|
||||
+
|
||||
rc = execWithRedirect(
|
||||
"grub2-mkconfig",
|
||||
- ["-o", "/etc/grub2.cfg"],
|
||||
+ ["-o", grub_cfg_path],
|
||||
root=sysroot
|
||||
)
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -4,19 +4,20 @@ Date: Thu, 18 Jun 2020 17:13:47 +0800
|
||||
Subject: [PATCH] fix hostname info
|
||||
|
||||
---
|
||||
po/zh_CN.po | 5 +++--
|
||||
po/zh_CN.po | 6 +++---
|
||||
pyanaconda/core/regexes.py | 2 +-
|
||||
pyanaconda/network.py | 3 ++-
|
||||
3 files changed, 6 insertions(+), 4 deletions(-)
|
||||
pyanaconda/network.py | 4 ++--
|
||||
3 files changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/po/zh_CN.po b/po/zh_CN.po
|
||||
index e31f0b2..c02ce1e 100644
|
||||
index 18b0925..c2216e6 100644
|
||||
--- a/po/zh_CN.po
|
||||
+++ b/po/zh_CN.po
|
||||
@@ -4090,10 +4090,11 @@ msgstr "本地主机名不能以英文句号“.”结尾。"
|
||||
@@ -4089,11 +4089,11 @@ msgstr "本地主机名不能以英文句号“.”结尾。"
|
||||
#: pyanaconda/network.py:119
|
||||
msgid ""
|
||||
"Host names can only contain the characters 'a-z', 'A-Z', '0-9', '-', or '.', "
|
||||
"parts between periods must contain something and cannot start or end with "
|
||||
-"parts between periods must contain something and cannot start or end with "
|
||||
-"'-'."
|
||||
+"parts between periods must contain something being 63 or fewer "
|
||||
+"characters and cannot start or end with '.' and '-'."
|
||||
@ -41,13 +42,14 @@ index cc00702..388d1ff 100644
|
||||
# URL Hostname
|
||||
# This matches any hostname, IPv4 literal or properly encased IPv6 literal
|
||||
diff --git a/pyanaconda/network.py b/pyanaconda/network.py
|
||||
index 38fe957..c52cf1d 100644
|
||||
index 38fe957..8f04d63 100644
|
||||
--- a/pyanaconda/network.py
|
||||
+++ b/pyanaconda/network.py
|
||||
@@ -115,7 +115,8 @@ def is_valid_hostname(hostname, local=False):
|
||||
@@ -114,8 +114,8 @@ def is_valid_hostname(hostname, local=False):
|
||||
if not re.match('^' + HOSTNAME_PATTERN_WITHOUT_ANCHORS + '$', hostname):
|
||||
return (False, _("Host names can only contain the characters 'a-z', "
|
||||
"'A-Z', '0-9', '-', or '.', parts between periods "
|
||||
"must contain something and cannot start or end with "
|
||||
- "must contain something and cannot start or end with "
|
||||
- "'-'."))
|
||||
+ "must contain something being 63 or fewer "
|
||||
+ "characters and cannot start or end with '.' and '-'."))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user