update anaconda to 36.16.5
(cherry picked from commit 2afd0aab87a649bacf1e37e03a2533b4a92b4d7e)
This commit is contained in:
parent
41c67ec90d
commit
8278796aac
@ -1,271 +0,0 @@
|
||||
From 32a54b5068c082a09683bfa81ac43b1b7b82fb8b Mon Sep 17 00:00:00 2001
|
||||
From: Wenlong Zhang <zhangwenlong@loongson.cn>
|
||||
Date: Tue, 18 Oct 2022 18:51:31 +0000
|
||||
Subject: [PATCH 6/7] install: add loongarch platform support
|
||||
|
||||
---
|
||||
pyanaconda/modules/storage/bootloader/base.py | 9 +-
|
||||
pyanaconda/modules/storage/bootloader/efi.py | 28 +++++-
|
||||
.../modules/storage/bootloader/factory.py | 7 ++
|
||||
.../modules/storage/bootloader/grub2.py | 1 +
|
||||
pyanaconda/modules/storage/bootloader/pmon.py | 87 +++++++++++++++++++
|
||||
.../modules/storage/devicetree/fsset.py | 6 +-
|
||||
pyanaconda/modules/storage/platform.py | 9 ++
|
||||
7 files changed, 142 insertions(+), 5 deletions(-)
|
||||
create mode 100644 pyanaconda/modules/storage/bootloader/pmon.py
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/bootloader/base.py b/pyanaconda/modules/storage/bootloader/base.py
|
||||
index 16a4df3..34bfae2 100644
|
||||
--- a/pyanaconda/modules/storage/bootloader/base.py
|
||||
+++ b/pyanaconda/modules/storage/bootloader/base.py
|
||||
@@ -731,11 +731,14 @@ class BootLoader(object):
|
||||
swap_devices = storage.fsset.swap_devices
|
||||
dracut_devices.extend(swap_devices)
|
||||
|
||||
- # Add resume= option to enable hibernation on x86.
|
||||
+ # Add resume= option to enable hibernation on x86 and loongarch.
|
||||
# Choose the largest swap device for that.
|
||||
- if blivet.arch.is_x86() and swap_devices:
|
||||
+ if (blivet.arch.is_x86() or blivet.arch.is_loongarch()) and swap_devices:
|
||||
resume_device = max(swap_devices, key=lambda x: x.size)
|
||||
- self.boot_args.add("resume=%s" % resume_device.fstab_spec)
|
||||
+ if not blivet.arch.is_efi() and blivet.arch.is_loongarch():
|
||||
+ self.boot_args.add("resume=%s" % resume_device.path)
|
||||
+ else:
|
||||
+ self.boot_args.add("resume=%s" % resume_device.fstab_spec)
|
||||
|
||||
# Does /usr have its own device? If so, we need to tell dracut
|
||||
usr_device = storage.mountpoints.get("/usr")
|
||||
diff --git a/pyanaconda/modules/storage/bootloader/efi.py b/pyanaconda/modules/storage/bootloader/efi.py
|
||||
index d8b7f10..1aed536 100644
|
||||
--- a/pyanaconda/modules/storage/bootloader/efi.py
|
||||
+++ b/pyanaconda/modules/storage/bootloader/efi.py
|
||||
@@ -28,7 +28,7 @@ from pyanaconda.product import productName
|
||||
from pyanaconda.anaconda_loggers import get_module_logger
|
||||
log = get_module_logger(__name__)
|
||||
|
||||
-__all__ = ["EFIBase", "EFIGRUB", "Aarch64EFIGRUB", "ArmEFIGRUB", "MacEFIGRUB"]
|
||||
+__all__ = ["EFIBase", "EFIGRUB", "Aarch64EFIGRUB", "ArmEFIGRUB", "MacEFIGRUB", "LOONGARCHEFIGRUB"]
|
||||
|
||||
|
||||
class EFIBase(object):
|
||||
@@ -167,7 +167,33 @@ class Aarch64EFIGRUB(EFIGRUB):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._packages64 = ["grub2-efi-aa64", "shim-aa64"]
|
||||
+class LOONGARCHEFIGRUB(EFIGRUB):
|
||||
+ _efi_binary = "grubloongarch64.efi"
|
||||
+ stage2_is_valid_stage1 = False
|
||||
+ stage2_bootable = False
|
||||
+
|
||||
+ def __init__(self):
|
||||
+ super().__init__()
|
||||
+ self._packages64 = ["grub2-efi-loongarch64"]
|
||||
|
||||
+ def remove_efi_boot_target(self):
|
||||
+ return
|
||||
+
|
||||
+ def _add_single_efi_boot_target(self, partition):
|
||||
+ boot_disk = partition.disk
|
||||
+ boot_part_num = str(partition.parted_partition.number)
|
||||
+
|
||||
+ rc = util.execInSysroot("cp", ["-a", "/boot/efi/EFI/openEuler/" + self._efi_binary, "/boot/efi/EFI/BOOT/" + "BOOTLOONGARCH64.EFI"])
|
||||
+ if rc:
|
||||
+ raise BootLoaderError("Failed to set new efi boot target. This is most "
|
||||
+ "likely a kernel or firmware bug.")
|
||||
+
|
||||
+ def add_efi_boot_target(self):
|
||||
+ if self.stage1_device.type == "partition": # pylint: disable=no-member
|
||||
+ self._add_single_efi_boot_target(self.stage1_device) # pylint: disable=no-member
|
||||
+ elif self.stage1_device.type == "mdarray": # pylint: disable=no-member
|
||||
+ for parent in self.stage1_device.parents: # pylint: disable=no-member
|
||||
+ self._add_single_efi_boot_target(parent)
|
||||
|
||||
class ArmEFIGRUB(EFIGRUB):
|
||||
_serial_consoles = ["ttyAMA", "ttyS"]
|
||||
diff --git a/pyanaconda/modules/storage/bootloader/factory.py b/pyanaconda/modules/storage/bootloader/factory.py
|
||||
index 8aa3afb..b5b8b59 100644
|
||||
--- a/pyanaconda/modules/storage/bootloader/factory.py
|
||||
+++ b/pyanaconda/modules/storage/bootloader/factory.py
|
||||
@@ -137,6 +137,13 @@ class BootLoaderFactory(object):
|
||||
if platform_class is platform.Aarch64EFI:
|
||||
from pyanaconda.modules.storage.bootloader.efi import Aarch64EFIGRUB
|
||||
return Aarch64EFIGRUB
|
||||
+ if platform_class is platform.LOONGARCHEFI:
|
||||
+ from pyanaconda.modules.storage.bootloader.efi import LOONGARCHEFIGRUB
|
||||
+ return LOONGARCHEFIGRUB
|
||||
+
|
||||
+ if platform_class is platform.LOONGARCHLEGACY:
|
||||
+ from pyanaconda.modules.storage.bootloader.pmon import LOONGARCHPMON
|
||||
+ return LOONGARCHPMON
|
||||
|
||||
if platform_class is platform.ARM:
|
||||
from pyanaconda.modules.storage.bootloader.extlinux import EXTLINUX
|
||||
diff --git a/pyanaconda/modules/storage/bootloader/grub2.py b/pyanaconda/modules/storage/bootloader/grub2.py
|
||||
index 51f7c74..57cfd95 100644
|
||||
--- a/pyanaconda/modules/storage/bootloader/grub2.py
|
||||
+++ b/pyanaconda/modules/storage/bootloader/grub2.py
|
||||
@@ -257,6 +257,7 @@ class GRUB2(BootLoader):
|
||||
defaults.write("GRUB_DISTRIBUTOR=\"$(sed 's, release .*$,,g' /etc/system-release)\"\n")
|
||||
defaults.write("GRUB_DEFAULT=saved\n")
|
||||
defaults.write("GRUB_DISABLE_SUBMENU=true\n")
|
||||
+ defaults.write("GRUB_CMDLINE_LINUX_DEFAULT=' rhgb quiet '\n")
|
||||
if self.console and self.has_serial_console:
|
||||
defaults.write("GRUB_TERMINAL=\"serial console\"\n")
|
||||
defaults.write("GRUB_SERIAL_COMMAND=\"%s\"\n" % self.serial_command)
|
||||
diff --git a/pyanaconda/modules/storage/bootloader/pmon.py b/pyanaconda/modules/storage/bootloader/pmon.py
|
||||
new file mode 100644
|
||||
index 0000000..7e02f61
|
||||
--- /dev/null
|
||||
+++ b/pyanaconda/modules/storage/bootloader/pmon.py
|
||||
@@ -0,0 +1,87 @@
|
||||
+#
|
||||
+# Writer: Sun Haiyong (youbest@sina.com)
|
||||
+#
|
||||
+import os
|
||||
+
|
||||
+from pyanaconda.modules.storage.bootloader.base import BootLoader, Arguments, BootLoaderError
|
||||
+from pyanaconda.core import util
|
||||
+from pyanaconda.core.configuration.anaconda import conf
|
||||
+from pyanaconda.product import productName
|
||||
+
|
||||
+from pyanaconda.anaconda_loggers import get_module_logger
|
||||
+log = get_module_logger(__name__)
|
||||
+
|
||||
+__all__ = ["PMON", "LOONGARCHPMON"]
|
||||
+
|
||||
+
|
||||
+class PMON(BootLoader):
|
||||
+ name = "PMON"
|
||||
+ _config_file = "boot.cfg"
|
||||
+ _config_dir = "/boot"
|
||||
+
|
||||
+ stage2_format_types = ["ext3", "ext2"]
|
||||
+ stage2_device_types = ["partition"]
|
||||
+# stage2_bootable = True
|
||||
+
|
||||
+ @property
|
||||
+ def config_file(self):
|
||||
+ return "%s/%s" % (self._config_dir, self._config_file)
|
||||
+
|
||||
+ @property
|
||||
+ def boot_prefix(self):
|
||||
+ """ Prefix, if any, to paths in /boot. """
|
||||
+ if self.stage2_device.format.mountpoint == "/":
|
||||
+ prefix = "/boot"
|
||||
+ else:
|
||||
+ prefix = ""
|
||||
+
|
||||
+ return prefix
|
||||
+
|
||||
+ def write_config_console(self, config):
|
||||
+ if not self.console:
|
||||
+ return
|
||||
+
|
||||
+ console_arg = "console=%s" % self.console
|
||||
+ if self.console_options:
|
||||
+ console_arg += ",%s" % self.console_options
|
||||
+ self.boot_args.add(console_arg)
|
||||
+
|
||||
+ def write_config_images(self, config):
|
||||
+ self.write_config_console(config)
|
||||
+ for image in self.images:
|
||||
+ args = Arguments()
|
||||
+ args.update(["root=%s" % image.device.path, "ro"])
|
||||
+ args.update(self.boot_args)
|
||||
+ log.info("bootloader.py: used boot args: %s ", args)
|
||||
+
|
||||
+ # extlinux labels cannot have spaces
|
||||
+ label = "%s(%s)" % (self.image_label(image), image.version)
|
||||
+ label = label.replace(" ", "")
|
||||
+ stanza = ("title %(label)s\n"
|
||||
+ "\tkernel /dev/fs/ext2@wd0%(boot_prefix)s/%(kernel)s\n"
|
||||
+ "\tinitrd /dev/fs/ext2@wd0%(boot_prefix)s/%(initrd)s\n"
|
||||
+ "\targs %(args)s\n\n"
|
||||
+ % {"label": label,
|
||||
+ "kernel": image.kernel,
|
||||
+ "initrd": image.initrd,
|
||||
+ "args": args,
|
||||
+ "boot_prefix": self.boot_prefix})
|
||||
+ config.write(stanza)
|
||||
+
|
||||
+ def write_config_header(self, config):
|
||||
+ header = ("timeout %(timeout)d\n"
|
||||
+ "showmenu 1\n"
|
||||
+ % {"timeout": self.timeout})
|
||||
+ config.write(header)
|
||||
+ if self.default is not None:
|
||||
+ config.write("default 0\n\n")
|
||||
+
|
||||
+ def install(self, args=None):
|
||||
+ """installation should be a no-op, just writing the config is sufficient for the
|
||||
+ firmware's bootloader (petitboot)
|
||||
+ """
|
||||
+ pass
|
||||
+
|
||||
+
|
||||
+class LOONGARCHPMON(PMON):
|
||||
+ """ LOONGARCHPMON """
|
||||
diff --git a/pyanaconda/modules/storage/devicetree/fsset.py b/pyanaconda/modules/storage/devicetree/fsset.py
|
||||
index 00aef10..ab7cd6f 100644
|
||||
--- a/pyanaconda/modules/storage/devicetree/fsset.py
|
||||
+++ b/pyanaconda/modules/storage/devicetree/fsset.py
|
||||
@@ -24,6 +24,7 @@ import gi
|
||||
gi.require_version("BlockDev", "2.0")
|
||||
from gi.repository import BlockDev as blockdev
|
||||
|
||||
+from blivet import arch
|
||||
from blivet.devices import NoDevice, DirectoryDevice, NFSDevice, FileDevice, MDRaidArrayDevice, \
|
||||
NetworkStorageDevice, OpticalDevice
|
||||
from blivet.errors import UnrecognizedFSTabEntryError, FSTabTypeMismatchError
|
||||
@@ -764,7 +765,10 @@ class FSSet(object):
|
||||
break
|
||||
if device.encrypted:
|
||||
options += ",x-systemd.device-timeout=0"
|
||||
- devspec = device.fstab_spec
|
||||
+ if not arch.is_efi() and arch.is_loongarch():
|
||||
+ devspec = device.path
|
||||
+ else:
|
||||
+ devspec = device.fstab_spec
|
||||
dump = device.format.dump
|
||||
if device.format.check and mountpoint == "/":
|
||||
passno = 1
|
||||
diff --git a/pyanaconda/modules/storage/platform.py b/pyanaconda/modules/storage/platform.py
|
||||
index 1023c93..9b730c1 100644
|
||||
--- a/pyanaconda/modules/storage/platform.py
|
||||
+++ b/pyanaconda/modules/storage/platform.py
|
||||
@@ -181,10 +181,15 @@ class MacEFI(EFI):
|
||||
class Aarch64EFI(EFI):
|
||||
_non_linux_format_types = ["vfat", "ntfs"]
|
||||
|
||||
+class LOONGARCHEFI(EFI):
|
||||
+ _non_linux_format_types = ["vfat", "ntfs"]
|
||||
|
||||
class ArmEFI(EFI):
|
||||
_non_linux_format_types = ["vfat", "ntfs"]
|
||||
|
||||
+class LOONGARCHLEGACY(Platform):
|
||||
+ _boot_stage1_device_types = ["partition"]
|
||||
+ _boot_descriptions = {"partition": Platform._boot_partition_description}
|
||||
|
||||
class PPC(Platform):
|
||||
_ppc_machine = arch.get_ppc_machine()
|
||||
@@ -288,12 +293,16 @@ def get_platform():
|
||||
return Aarch64EFI()
|
||||
elif arch.is_arm():
|
||||
return ArmEFI()
|
||||
+ elif arch.is_loongarch():
|
||||
+ return LOONGARCHEFI()
|
||||
else:
|
||||
return EFI()
|
||||
elif arch.is_x86():
|
||||
return X86()
|
||||
elif arch.is_arm():
|
||||
return ARM()
|
||||
+ elif arch.is_loongarch():
|
||||
+ return LOONGARCHLEGACY()
|
||||
else:
|
||||
raise SystemError("Could not determine system architecture.")
|
||||
|
||||
--
|
||||
2.27.0
|
||||
@ -1,27 +0,0 @@
|
||||
From f4a9c3a8588ec5a6563d76a0a4d319e078912f01 Mon Sep 17 00:00:00 2001
|
||||
From: sherlock2010 <15151851377@163.com>
|
||||
Date: Thu, 10 Dec 2020 14:26:12 +0800
|
||||
Subject: [PATCH] Change length limit of hostname from 255 to 64
|
||||
|
||||
---
|
||||
pyanaconda/network.py | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/network.py b/pyanaconda/network.py
|
||||
index 6aab84a..00ccd0a 100644
|
||||
--- a/pyanaconda/network.py
|
||||
+++ b/pyanaconda/network.py
|
||||
@@ -109,8 +109,8 @@ def is_valid_hostname(hostname, local=False):
|
||||
if not hostname:
|
||||
return (False, _("Host name cannot be None or an empty string."))
|
||||
|
||||
- if len(hostname) > 255:
|
||||
- return (False, _("Host name must be 255 or fewer characters in length."))
|
||||
+ if len(hostname) > 64:
|
||||
+ return (False, _("Host name must be 64 or fewer characters in length."))
|
||||
|
||||
if local and hostname[-1] == ".":
|
||||
return (False, _("Local host name must not end with period '.'."))
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
From 407e03ec54d6abbce265d7127bab863602e38720 Mon Sep 17 00:00:00 2001
|
||||
From: wangce <wangce@uniontech.com>
|
||||
Date: Tue, 10 Aug 2021 09:36:35 +0600
|
||||
Subject: [PATCH 2/2] Change sidebar background size
|
||||
|
||||
---
|
||||
data/anaconda-gtk.css | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/data/anaconda-gtk.css b/data/anaconda-gtk.css
|
||||
index 85119ea..2f6963d 100644
|
||||
--- a/data/anaconda-gtk.css
|
||||
+++ b/data/anaconda-gtk.css
|
||||
@@ -107,6 +107,7 @@ infobar.error {
|
||||
background-image: url('/usr/share/anaconda/pixmaps/sidebar-bg.png');
|
||||
background-color: @product_bg_color;
|
||||
background-repeat: no-repeat;
|
||||
+ background-size: 100% 100%;
|
||||
}
|
||||
|
||||
/* Add a logo to the sidebar */
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
diff -uNrp a/data/anaconda-gtk.css b/data/anaconda-gtk.css
|
||||
--- a/data/anaconda-gtk.css 2019-08-21 18:50:27.188000000 +0800
|
||||
+++ b/data/anaconda-gtk.css 2019-08-21 18:52:23.172000000 +0800
|
||||
@@ -112,7 +112,8 @@ levelbar.discrete trough block.filled.hi
|
||||
AnacondaSpokeWindow #nav-box {
|
||||
background-color: @product_bg_color;
|
||||
background-image: url('/usr/share/anaconda/pixmaps/topbar-bg.png');
|
||||
- background-repeat: repeat;
|
||||
+ background-repeat: no-repeat;
|
||||
+ background-size: 100% 100%;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
From 3216e5fc1c39354e66c977f76465303ea2a11859 Mon Sep 17 00:00:00 2001
|
||||
From: t_feng <fengtao40@huawei.com>
|
||||
Date: Thu, 18 Jun 2020 16:45:27 +0800
|
||||
Subject: [PATCH] Fix hiding of network device activation switch
|
||||
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/network.py | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/network.py b/pyanaconda/ui/gui/spokes/network.py
|
||||
index d6c1e4b..1318e17 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/network.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/network.py
|
||||
@@ -1019,8 +1019,10 @@ class NetworkControlBox(GObject.GObject):
|
||||
|
||||
switch = self.builder.get_object("device_%s_off_switch" % dev_type_str)
|
||||
if dev_type_str == "wired":
|
||||
- switch.set_visible(state not in (NM.DeviceState.UNAVAILABLE,
|
||||
- NM.DeviceState.UNMANAGED))
|
||||
+ visible = state not in (NM.DeviceState.UNAVAILABLE, NM.DeviceState.UNMANAGED)
|
||||
+ switch.set_visible(visible)
|
||||
+ if not visible:
|
||||
+ switch.set_no_show_all(True)
|
||||
self._updating_device = True
|
||||
switch.set_active(state not in (NM.DeviceState.UNMANAGED,
|
||||
NM.DeviceState.UNAVAILABLE,
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,28 +1,41 @@
|
||||
From 8f6a97734a9ecb63320d73ec42efd6f4c03eac5b Mon Sep 17 00:00:00 2001
|
||||
From 65258a808a703de25f790b2cb5aff8e734228ad1 Mon Sep 17 00:00:00 2001
|
||||
From: Qiumiao Zhang <zhangqiumiao1@huawei.com>
|
||||
Date: Thu, 7 Apr 2022 03:41:52 -0400
|
||||
Date: Mon, 7 Nov 2022 11:33:53 +0800
|
||||
Subject: [PATCH] Support configuration of additional boot arguments
|
||||
|
||||
---
|
||||
data/anaconda.conf | 3 +++
|
||||
data/anaconda.conf | 2 ++
|
||||
pyanaconda/argument_parsing.py | 2 +-
|
||||
pyanaconda/core/configuration/bootloader.py | 8 ++++++++
|
||||
pyanaconda/modules/storage/bootloader/base.py | 5 +++++
|
||||
3 files changed, 16 insertions(+)
|
||||
4 files changed, 16 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/data/anaconda.conf b/data/anaconda.conf
|
||||
index c622700..3e63c50 100644
|
||||
index 703114a..b80440e 100644
|
||||
--- a/data/anaconda.conf
|
||||
+++ b/data/anaconda.conf
|
||||
@@ -134,6 +134,9 @@ preserved_arguments =
|
||||
biosdevname ipv6.disable net.ifnames net.ifnames.prefix
|
||||
nosmt
|
||||
@@ -159,6 +159,8 @@ preserved_arguments =
|
||||
biosdevname ipv6.disable net.ifnames net.ifnames.prefix
|
||||
nosmt
|
||||
|
||||
+# Arguments added by default.
|
||||
+additional_arguments =
|
||||
+
|
||||
|
||||
[Storage]
|
||||
# Enable dmraid usage during the installation.
|
||||
diff --git a/pyanaconda/argument_parsing.py b/pyanaconda/argument_parsing.py
|
||||
index 75f28f4..dd5ecdf 100644
|
||||
--- a/pyanaconda/argument_parsing.py
|
||||
+++ b/pyanaconda/argument_parsing.py
|
||||
@@ -589,7 +589,7 @@ def getArgumentParser(version_string, boot_cmdline=None):
|
||||
|
||||
# some defaults change based on cmdline flags
|
||||
if boot_cmdline is not None:
|
||||
- if "console" in boot_cmdline:
|
||||
+ if "console" in boot_cmdline and "inst.text" in boot_cmdline:
|
||||
ap.set_defaults(display_mode=DisplayModes.TUI)
|
||||
|
||||
return ap
|
||||
diff --git a/pyanaconda/core/configuration/bootloader.py b/pyanaconda/core/configuration/bootloader.py
|
||||
index 6746e45..7b782d3 100644
|
||||
--- a/pyanaconda/core/configuration/bootloader.py
|
||||
@ -40,18 +53,18 @@ index 6746e45..7b782d3 100644
|
||||
+ """
|
||||
+ return self._get_option("additional_arguments", str).split()
|
||||
diff --git a/pyanaconda/modules/storage/bootloader/base.py b/pyanaconda/modules/storage/bootloader/base.py
|
||||
index a45a530..db98693 100644
|
||||
index be039c4..533d528 100644
|
||||
--- a/pyanaconda/modules/storage/bootloader/base.py
|
||||
+++ b/pyanaconda/modules/storage/bootloader/base.py
|
||||
@@ -707,6 +707,7 @@ class BootLoader(object):
|
||||
self._set_extra_boot_args()
|
||||
@@ -734,6 +734,7 @@ class BootLoader(object):
|
||||
self._set_extra_boot_args(bootloader_proxy)
|
||||
self._set_storage_boot_args(storage)
|
||||
self._preserve_some_boot_args()
|
||||
+ self._add_additional_boot_args()
|
||||
self._set_graphical_boot_args()
|
||||
self._set_security_boot_args()
|
||||
|
||||
@@ -843,6 +844,10 @@ class BootLoader(object):
|
||||
@@ -908,6 +909,10 @@ class BootLoader(object):
|
||||
|
||||
self.boot_args.add(new_arg)
|
||||
|
||||
|
||||
@ -1,29 +1,45 @@
|
||||
From e8ce5155f21af58e119c61e10895fcb5d8c21995 Mon Sep 17 00:00:00 2001
|
||||
From: t_feng <fengtao40@huawei.com>
|
||||
Date: Thu, 18 Jun 2020 17:00:13 +0800
|
||||
From 3562cad5ea86afc5d2ce0ead649e64cf13e39128 Mon Sep 17 00:00:00 2001
|
||||
From: sun_hai_10 <sunhai10@huawei.com>
|
||||
Date: Mon, 7 Nov 2022 14:48:28 +0800
|
||||
Subject: [PATCH] add passwd policy
|
||||
|
||||
---
|
||||
data/interactive-defaults.ks | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
data/anaconda.conf | 6 +++---
|
||||
pyanaconda/input_checking.py | 4 ++++
|
||||
2 files changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/data/interactive-defaults.ks b/data/interactive-defaults.ks
|
||||
index a906c8c..0177cf9 100644
|
||||
--- a/data/interactive-defaults.ks
|
||||
+++ b/data/interactive-defaults.ks
|
||||
@@ -4,9 +4,9 @@ firstboot --enable
|
||||
diff --git a/data/anaconda.conf b/data/anaconda.conf
|
||||
index 703114a..07e500f 100644
|
||||
--- a/data/anaconda.conf
|
||||
+++ b/data/anaconda.conf
|
||||
@@ -308,9 +308,9 @@ can_change_users = False
|
||||
# strict Require the minimum quality.
|
||||
#
|
||||
password_policies =
|
||||
- root (quality 1, length 6)
|
||||
- user (quality 1, length 6, empty)
|
||||
- luks (quality 1, length 6)
|
||||
+ root (quality 1, length 8, strict)
|
||||
+ user (quality 1, length 8, empty, strict)
|
||||
+ luks (quality 1, length 8, strict)
|
||||
|
||||
%anaconda
|
||||
# Default password policies
|
||||
-pwpolicy root --notstrict --minlen=6 --minquality=1 --nochanges --notempty
|
||||
-pwpolicy user --notstrict --minlen=6 --minquality=1 --nochanges --emptyok
|
||||
-pwpolicy luks --notstrict --minlen=6 --minquality=1 --nochanges --notempty
|
||||
+pwpolicy root --notstrict --minlen=8 --minquality=1 --nochanges --notempty
|
||||
+pwpolicy user --notstrict --minlen=8 --minquality=1 --nochanges --emptyok
|
||||
+pwpolicy luks --notstrict --minlen=8 --minquality=1 --nochanges --notempty
|
||||
# NOTE: This applies only to *fully* interactive installations, partial kickstart
|
||||
# installations use defaults specified in pyanaconda/pwpolicy.py.
|
||||
# Automated kickstart installs simply ignore the password policy as the policy
|
||||
|
||||
[License]
|
||||
diff --git a/pyanaconda/input_checking.py b/pyanaconda/input_checking.py
|
||||
index 4482b26..4bed6c1 100644
|
||||
--- a/pyanaconda/input_checking.py
|
||||
+++ b/pyanaconda/input_checking.py
|
||||
@@ -421,6 +421,10 @@ class PasswordValidityCheck(InputCheck):
|
||||
pw_score = 4
|
||||
status_text = _(constants.SecretStatus.STRONG.value)
|
||||
|
||||
+ #disable set password without confirnation
|
||||
+ if not error_message and not check_request.password_confirmation:
|
||||
+ error_message = _(constants.SECRET_CONFIRM_ERROR_GUI[check_request.secret_type])
|
||||
+
|
||||
# the policy influences the overall success of the check
|
||||
# - score 0 & strict == True -> success = False
|
||||
# - score 0 & strict == False -> success = True
|
||||
--
|
||||
2.23.0
|
||||
|
||||
|
||||
@ -1,124 +0,0 @@
|
||||
diff -Nuar anaconda-33.19.org/pyanaconda/modules/storage/bootloader/factory.py anaconda-33.19.sw/pyanaconda/modules/storage/bootloader/factory.py
|
||||
--- anaconda-33.19.org/pyanaconda/modules/storage/bootloader/factory.py 2022-09-07 14:50:46.860000000 +0800
|
||||
+++ anaconda-33.19.sw/pyanaconda/modules/storage/bootloader/factory.py 2022-09-07 14:50:57.380000000 +0800
|
||||
@@ -106,6 +106,10 @@
|
||||
platform_class = platform.platform.__class__
|
||||
|
||||
# Get the type of the bootloader.
|
||||
+ if platform_class is platform.Sw_64:
|
||||
+ from pyanaconda.modules.storage.bootloader.grub2 import GRUB2
|
||||
+ return GRUB2
|
||||
+
|
||||
if platform_class is platform.X86:
|
||||
from pyanaconda.modules.storage.bootloader.grub2 import GRUB2
|
||||
return GRUB2
|
||||
diff -Nuar anaconda-33.19.org/pyanaconda/modules/storage/bootloader/grub2.py anaconda-33.19.sw/pyanaconda/modules/storage/bootloader/grub2.py
|
||||
--- anaconda-33.19.org/pyanaconda/modules/storage/bootloader/grub2.py 2022-09-07 14:50:46.860000000 +0800
|
||||
+++ anaconda-33.19.sw/pyanaconda/modules/storage/bootloader/grub2.py 2022-09-07 14:56:42.550000000 +0800
|
||||
@@ -101,7 +101,7 @@
|
||||
name = "GRUB2"
|
||||
# grub2 is a virtual provides that's provided by grub2-pc, grub2-ppc64le,
|
||||
# and all of the primary grub components that aren't grub2-efi-${EFIARCH}
|
||||
- packages = ["grub2", "grub2-tools"]
|
||||
+ packages = ["grub2-common", "grub2-tools"]
|
||||
_config_file = "grub.cfg"
|
||||
_config_dir = "grub2"
|
||||
_passwd_file = "user.cfg"
|
||||
@@ -453,16 +453,47 @@
|
||||
return
|
||||
|
||||
try:
|
||||
- self.write_device_map()
|
||||
- self.stage2_device.format.sync(root=conf.target.physical_root)
|
||||
- os.sync()
|
||||
- self.install()
|
||||
- os.sync()
|
||||
- self.stage2_device.format.sync(root=conf.target.physical_root)
|
||||
+ if os.path.exists("/mnt/sysroot/boot/grub"):
|
||||
+ FileName="/mnt/sysroot/boot/grub/grub.cfg"
|
||||
+ f=open(FileName,"w+")
|
||||
+ f.write("# SW_64 Grub default configurations\n")
|
||||
+ f.write("set default=0\n")
|
||||
+ f.write("set timeout=10\n")
|
||||
+ f.write("\n")
|
||||
+ f.write("set menu_color_normal=white/black\n")
|
||||
+ f.write("set menu_color_highlight=light-red/black\n")
|
||||
+ f.write("\n")
|
||||
+ f.write("loadfont ${prefix}/fonts/unicode.pf2\n")
|
||||
+ f.write("insmod efi_gop\n")
|
||||
+ f.write("set lang=zh_CN\n")
|
||||
+ f.write("set gfxmode=800x600\n")
|
||||
+ f.write("set gfxplayload=auto\n")
|
||||
+ f.write("terminal_output gfxterm\n")
|
||||
+ f.write("background_color 64,0,64\n")
|
||||
+ f.write("\n")
|
||||
+ f.write("menuentry 'openEuler 22.03 LTS SP1' --class gnu-linux --class gnu --class os{\n")
|
||||
+ f.write("echo \"Loading, please wait for a moment......\"\n")
|
||||
+ f.write ("set boot=(${root})\n")
|
||||
+ f.write("echo \"Loading boot\"\n")
|
||||
+ f.write ("linux.boot ${boot}/initramfs-5.10.0-39.0.0.21.sw_64.img\n")
|
||||
+ f.write("echo \"Loading vmlinuz\"\n")
|
||||
+ f.write("linux.vmlinux ${boot}/vmlinuz-5.10.0-39.0.0.21.sw_64 root=/dev/mapper/openeuler-root rootdelay=60 net.ifnames=0 loglevel=0 vga=current rd.systemd.show_status=false rd.udev.log-priority=3 quiet splash video=sm750fb:1280x1024@60 cgroup.memory=nokmem notc\n")
|
||||
+ f.write("echo \"Booting......\"\n")
|
||||
+ f.write("boot\n")
|
||||
+ f.write("}")
|
||||
+ f.close()
|
||||
+ else:
|
||||
+ self.write_device_map()
|
||||
+ self.stage2_device.format.sync(root=conf.target.physical_root)
|
||||
+ os.sync()
|
||||
+ self.install()
|
||||
+ os.sync()
|
||||
+ self.stage2_device.format.sync(root=conf.target.physical_root)
|
||||
finally:
|
||||
- self.write_config()
|
||||
- os.sync()
|
||||
- self.stage2_device.format.sync(root=conf.target.physical_root)
|
||||
+ pass
|
||||
+ #self.write_config()
|
||||
+ #os.sync()
|
||||
+ #self.stage2_device.format.sync(root=conf.target.physical_root)
|
||||
|
||||
def check(self):
|
||||
"""When installing to the mbr of a disk grub2 needs enough space
|
||||
diff -Nuar anaconda-33.19.org/pyanaconda/modules/storage/platform.py anaconda-33.19.sw/pyanaconda/modules/storage/platform.py
|
||||
--- anaconda-33.19.org/pyanaconda/modules/storage/platform.py 2022-09-07 14:50:46.850000000 +0800
|
||||
+++ anaconda-33.19.sw/pyanaconda/modules/storage/platform.py 2022-09-07 14:50:57.380000000 +0800
|
||||
@@ -116,6 +116,17 @@
|
||||
selection fails."""
|
||||
return self._boot_stage1_missing_error
|
||||
|
||||
+class Sw_64(Platform):
|
||||
+ _boot_stage1_device_types = ["disk"]
|
||||
+ _boot_mbr_description = N_("Master Boot Record")
|
||||
+ _boot_descriptions = {"disk": _boot_mbr_description,
|
||||
+ "partition": Platform._boot_partition_description,
|
||||
+ "mdarray": Platform._boot_raid_description}
|
||||
+
|
||||
+ # XXX hpfs, if reported by blkid/udev, will end up with a type of None
|
||||
+ _non_linux_format_types = ["vfat", "ntfs", "hpfs"]
|
||||
+ _boot_stage1_missing_error = N_("You must include at least one MBR- or "
|
||||
+ "GPT-formatted disk as an install target.")
|
||||
|
||||
class X86(Platform):
|
||||
_boot_stage1_device_types = ["disk"]
|
||||
@@ -281,6 +292,8 @@
|
||||
raise SystemError("Unsupported PPC machine type: %s" % ppc_machine)
|
||||
elif arch.is_s390():
|
||||
return S390()
|
||||
+ elif arch.is_sw_64():
|
||||
+ return Sw_64()
|
||||
elif arch.is_efi():
|
||||
if arch.is_mactel():
|
||||
return MacEFI()
|
||||
diff -Nuar anaconda-33.19.org/tests/nosetests/pyanaconda_tests/module_bootloader_test.py anaconda-33.19.sw/tests/nosetests/pyanaconda_tests/module_bootloader_test.py
|
||||
--- anaconda-33.19.org/tests/nosetests/pyanaconda_tests/module_bootloader_test.py 2022-09-07 14:50:46.610000000 +0800
|
||||
+++ anaconda-33.19.sw/tests/nosetests/pyanaconda_tests/module_bootloader_test.py 2022-09-07 14:50:57.130000000 +0800
|
||||
@@ -393,6 +393,7 @@
|
||||
# Test known platforms.
|
||||
boot_loader_by_platform = {
|
||||
platform.X86: GRUB2,
|
||||
+ platform.Sw_64: GRUB2,
|
||||
platform.EFI: EFIGRUB,
|
||||
platform.MacEFI: MacEFIGRUB,
|
||||
platform.PPC: GRUB2,
|
||||
Binary file not shown.
BIN
anaconda-36.16.5.tar.bz2
Normal file
BIN
anaconda-36.16.5.tar.bz2
Normal file
Binary file not shown.
@ -1,127 +0,0 @@
|
||||
From 4e699fe30da24771b80ff1fe64d7791bcb444f79 Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Tue, 21 Jul 2020 10:57:00 +0200
|
||||
Subject: [PATCH] Allow to detect devices with the iso9660 file system as
|
||||
optical media
|
||||
|
||||
Test that the DBus method FindOpticalMedia identifies devices with the iso9660 file
|
||||
system as optical media, so it is able to find NVDIMM devices with iso9660.
|
||||
|
||||
The DBus method GetDevicesToIgnore of the NVDIMM module shouldn't return NVDIMM
|
||||
devices with the iso9660 file system. They can be used as an installation source.
|
||||
|
||||
Protect all devices with the iso9660 file system. It will protect, for example, NVDIMM
|
||||
devices with the iso9660 file system that can be used only as an installation source
|
||||
anyway.
|
||||
|
||||
Related: rhbz#1856264
|
||||
---
|
||||
.../modules/storage/devicetree/model.py | 5 ++++
|
||||
pyanaconda/modules/storage/nvdimm/nvdimm.py | 12 ++++++++-
|
||||
.../module_device_tree_test.py | 27 ++++++++++++++++---
|
||||
3 files changed, 39 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/devicetree/model.py b/pyanaconda/modules/storage/devicetree/model.py
|
||||
index 4d0ecdb..cdee5a8 100644
|
||||
--- a/pyanaconda/modules/storage/devicetree/model.py
|
||||
+++ b/pyanaconda/modules/storage/devicetree/model.py
|
||||
@@ -303,6 +303,11 @@ class InstallerStorage(Blivet):
|
||||
# cdroms, involves unmounting which is undesirable (see bug #1671713).
|
||||
protected.extend(dev for dev in self.devicetree.devices if dev.type == "cdrom")
|
||||
|
||||
+ # Protect also all devices with an iso9660 file system. It will protect
|
||||
+ # NVDIMM devices that can be used only as an installation source anyway
|
||||
+ # (see the bug #1856264).
|
||||
+ protected.extend(dev for dev in self.devicetree.devices if dev.format.type == "iso9660")
|
||||
+
|
||||
# Mark the collected devices as protected.
|
||||
for dev in protected:
|
||||
log.debug("Marking device %s as protected.", dev.name)
|
||||
diff --git a/pyanaconda/modules/storage/nvdimm/nvdimm.py b/pyanaconda/modules/storage/nvdimm/nvdimm.py
|
||||
index 0bbcc6e..4476dd1 100644
|
||||
--- a/pyanaconda/modules/storage/nvdimm/nvdimm.py
|
||||
+++ b/pyanaconda/modules/storage/nvdimm/nvdimm.py
|
||||
@@ -21,6 +21,7 @@ import gi
|
||||
gi.require_version("BlockDev", "2.0")
|
||||
from gi.repository import BlockDev as blockdev
|
||||
|
||||
+from blivet import udev
|
||||
from blivet.static_data import nvdimm
|
||||
|
||||
from pykickstart.constants import NVDIMM_ACTION_RECONFIGURE, NVDIMM_ACTION_USE
|
||||
@@ -90,6 +91,9 @@ class NVDIMMModule(KickstartBaseModule):
|
||||
installation, the device(s) must be specified by nvdimm kickstart
|
||||
command. Also, only devices in sector mode are allowed.
|
||||
|
||||
+ Don't ignore devices that have an iso9660 file system. We might
|
||||
+ want to use them as an installation source.
|
||||
+
|
||||
:return: a set of device names
|
||||
"""
|
||||
namespaces_to_use = self.get_namespaces_to_use()
|
||||
@@ -97,7 +101,13 @@ class NVDIMMModule(KickstartBaseModule):
|
||||
devices_to_ignore = set()
|
||||
|
||||
for ns_name, ns_info in nvdimm.namespaces.items():
|
||||
- if ns_info.mode != blockdev.NVDIMMNamespaceMode.SECTOR:
|
||||
+ info = udev.get_device(device_node="/dev/" + ns_info.blockdev)
|
||||
+
|
||||
+ if info and udev.device_get_format(info) == "iso9660":
|
||||
+ log.debug("%s / %s won't be ignored - NVDIMM device has "
|
||||
+ "an iso9660 file system", ns_name, ns_info.blockdev)
|
||||
+ continue
|
||||
+ elif ns_info.mode != blockdev.NVDIMMNamespaceMode.SECTOR:
|
||||
log.debug("%s / %s will be ignored - NVDIMM device is not "
|
||||
"in sector mode", ns_name, ns_info.blockdev)
|
||||
elif ns_name not in namespaces_to_use and ns_info.blockdev not in devices_to_use:
|
||||
diff --git a/tests/nosetests/pyanaconda_tests/module_device_tree_test.py b/tests/nosetests/pyanaconda_tests/module_device_tree_test.py
|
||||
index 838c70e..5e52843 100644
|
||||
--- a/tests/nosetests/pyanaconda_tests/module_device_tree_test.py
|
||||
+++ b/tests/nosetests/pyanaconda_tests/module_device_tree_test.py
|
||||
@@ -24,10 +24,10 @@ from unittest.mock import patch, Mock, PropertyMock
|
||||
from tests.nosetests.pyanaconda_tests import patch_dbus_publish_object, check_task_creation
|
||||
|
||||
from blivet.devices import StorageDevice, DiskDevice, DASDDevice, ZFCPDiskDevice, PartitionDevice, \
|
||||
- LUKSDevice, iScsiDiskDevice, NVDIMMNamespaceDevice, FcoeDiskDevice
|
||||
+ LUKSDevice, iScsiDiskDevice, NVDIMMNamespaceDevice, FcoeDiskDevice, OpticalDevice
|
||||
from blivet.errors import StorageError, FSError
|
||||
from blivet.formats import get_format
|
||||
-from blivet.formats.fs import FS
|
||||
+from blivet.formats.fs import FS, Iso9660FS
|
||||
from blivet.formats.luks import LUKS
|
||||
from blivet.size import Size
|
||||
|
||||
@@ -627,9 +627,28 @@ class DeviceTreeInterfaceTestCase(unittest.TestCase):
|
||||
str(cm.exception), "Failed to unmount dev1 from /path: Fake error."
|
||||
)
|
||||
|
||||
- def find_install_media_test(self):
|
||||
+ @patch.object(Iso9660FS, "check_module")
|
||||
+ def find_install_media_test(self, check_module):
|
||||
"""Test FindInstallMedia."""
|
||||
- self.assertEqual(self.interface.FindOpticalMedia(), [])
|
||||
+ dev1 = OpticalDevice("dev1")
|
||||
+ dev1.size = Size("2 GiB")
|
||||
+ dev1.format = get_format("iso9660")
|
||||
+ dev1.controllable = True
|
||||
+ self._add_device(dev1)
|
||||
+
|
||||
+ dev2 = StorageDevice("dev2")
|
||||
+ dev2.size = Size("2 GiB")
|
||||
+ dev2.format = get_format("iso9660")
|
||||
+ dev2.controllable = True
|
||||
+ self._add_device(dev2)
|
||||
+
|
||||
+ dev3 = StorageDevice("dev3")
|
||||
+ dev3.size = Size("2 GiB")
|
||||
+ dev3.format = get_format("ext4")
|
||||
+ dev3.controllable = True
|
||||
+ self._add_device(dev3)
|
||||
+
|
||||
+ self.assertEqual(self.interface.FindOpticalMedia(), ["dev1", "dev2"])
|
||||
|
||||
@patch.object(FS, "update_size_info")
|
||||
def find_mountable_partitions_test(self, update_size_info):
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,642 +0,0 @@
|
||||
From 5283a20d41050551b54d6d12960ac28e0e5e1648 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Tue, 21 Jul 2020 11:17:40 +0200
|
||||
Subject: [PATCH] Fix stage2 as default sources
|
||||
|
||||
We should prioritize stage2 device as the default source.
|
||||
This is especially needed for DVD ISO because it is booting
|
||||
with inst.stage2 instead and we should use the DVD
|
||||
as the source for the default CDROM.
|
||||
The situation is even worse thanks to the fact that
|
||||
DVD ISOs are using inst.stage2=hd:...
|
||||
|
||||
Find stage2 device and test this device first during
|
||||
the auto-discover feature of CDRom source.
|
||||
|
||||
Resolves: rhbz#1856264
|
||||
---
|
||||
.../modules/payloads/source/cdrom/cdrom.py | 7 +-
|
||||
.../payloads/source/cdrom/cdrom_interface.py | 7 +-
|
||||
.../payloads/source/cdrom/initialization.py | 64 +++-
|
||||
pyanaconda/modules/payloads/source/utils.py | 8 +-
|
||||
.../modules/storage/devicetree/handler.py | 5 +-
|
||||
.../storage/devicetree/handler_interface.py | 5 +-
|
||||
pyanaconda/payload/utils.py | 2 +-
|
||||
.../module_device_tree_test.py | 23 +-
|
||||
.../module_source_cdrom_test.py | 286 ++++++++++++++++--
|
||||
9 files changed, 362 insertions(+), 45 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/payloads/source/cdrom/cdrom.py b/pyanaconda/modules/payloads/source/cdrom/cdrom.py
|
||||
index 93df362..bb751ae 100644
|
||||
--- a/pyanaconda/modules/payloads/source/cdrom/cdrom.py
|
||||
+++ b/pyanaconda/modules/payloads/source/cdrom/cdrom.py
|
||||
@@ -32,7 +32,12 @@ log = get_module_logger(__name__)
|
||||
|
||||
|
||||
class CdromSourceModule(PayloadSourceBase, MountingSourceMixin, RPMSourceMixin):
|
||||
- """The CD-ROM source payload module."""
|
||||
+ """The CD-ROM source payload module.
|
||||
+
|
||||
+ This source will try to automatically detect installation source. First it tries to look only
|
||||
+ stage2 device used to boot the environment then it will use first valid iso9660 media with a
|
||||
+ valid structure.
|
||||
+ """
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
diff --git a/pyanaconda/modules/payloads/source/cdrom/cdrom_interface.py b/pyanaconda/modules/payloads/source/cdrom/cdrom_interface.py
|
||||
index 0c5b6d7..74d2f14 100644
|
||||
--- a/pyanaconda/modules/payloads/source/cdrom/cdrom_interface.py
|
||||
+++ b/pyanaconda/modules/payloads/source/cdrom/cdrom_interface.py
|
||||
@@ -25,7 +25,12 @@ from pyanaconda.modules.payloads.source.source_base_interface import PayloadSour
|
||||
|
||||
@dbus_interface(PAYLOAD_SOURCE_CDROM.interface_name)
|
||||
class CdromSourceInterface(PayloadSourceBaseInterface):
|
||||
- """Interface for the payload CD-ROM image source."""
|
||||
+ """Interface for the payload CD-ROM image source.
|
||||
+
|
||||
+ This source will try to automatically detect installation source. First it tries to look only
|
||||
+ stage2 device used to boot the environment then it will use first valid iso9660 media with a
|
||||
+ valid structure.
|
||||
+ """
|
||||
|
||||
def connect_signals(self):
|
||||
super().connect_signals()
|
||||
diff --git a/pyanaconda/modules/payloads/source/cdrom/initialization.py b/pyanaconda/modules/payloads/source/cdrom/initialization.py
|
||||
index a182fcd..7fc38fc 100644
|
||||
--- a/pyanaconda/modules/payloads/source/cdrom/initialization.py
|
||||
+++ b/pyanaconda/modules/payloads/source/cdrom/initialization.py
|
||||
@@ -15,13 +15,15 @@
|
||||
# License and may only be used or replicated with the express permission of
|
||||
# Red Hat, Inc.
|
||||
#
|
||||
+from pyanaconda.core.kernel import kernel_arguments
|
||||
from pyanaconda.modules.common.constants.objects import DEVICE_TREE
|
||||
from pyanaconda.modules.common.constants.services import STORAGE
|
||||
from pyanaconda.modules.common.errors.payload import SourceSetupError
|
||||
-from pyanaconda.modules.payloads.source.mount_tasks import SetUpMountTask
|
||||
from pyanaconda.modules.common.structures.storage import DeviceData
|
||||
-from pyanaconda.payload.utils import mount, unmount, PayloadSetupError
|
||||
+from pyanaconda.modules.payloads.source.mount_tasks import SetUpMountTask
|
||||
from pyanaconda.modules.payloads.source.utils import is_valid_install_disk
|
||||
+from pyanaconda.payload.source.factory import SourceFactory, PayloadSourceTypeUnrecognized
|
||||
+from pyanaconda.payload.utils import mount, unmount, PayloadSetupError
|
||||
|
||||
from pyanaconda.anaconda_loggers import get_module_logger
|
||||
log = get_module_logger(__name__)
|
||||
@@ -37,13 +39,62 @@ class SetUpCdromSourceTask(SetUpMountTask):
|
||||
return "Set up CD-ROM Installation Source"
|
||||
|
||||
def _do_mount(self):
|
||||
- """Run CD-ROM installation source setup."""
|
||||
- log.debug("Trying to detect CD-ROM automatically")
|
||||
+ """Run CD-ROM installation source setup.
|
||||
|
||||
+ Try to discover installation media and mount that. Device used for booting (inst.stage2)
|
||||
+ has a priority.
|
||||
+ """
|
||||
+ log.debug("Trying to detect CD-ROM automatically")
|
||||
device_tree = STORAGE.get_proxy(DEVICE_TREE)
|
||||
+
|
||||
+ device_candidates = self._get_device_candidate_list(device_tree)
|
||||
+ device_name = self._choose_installation_device(device_tree, device_candidates)
|
||||
+
|
||||
+ if not device_name:
|
||||
+ raise SourceSetupError("Found no CD-ROM")
|
||||
+
|
||||
+ return device_name
|
||||
+
|
||||
+ def _get_device_candidate_list(self, device_tree):
|
||||
+ stage2_device = self._probe_stage2_for_cdrom(device_tree)
|
||||
+ device_candidates = device_tree.FindOpticalMedia()
|
||||
+
|
||||
+ if stage2_device in device_candidates:
|
||||
+ device_candidates = [stage2_device] + device_candidates
|
||||
+
|
||||
+ return device_candidates
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def _probe_stage2_for_cdrom(device_tree):
|
||||
+ # TODO: This is temporary method which should be moved closer to the inst.repo logic
|
||||
+ log.debug("Testing if inst.stage2 is a CDROM device")
|
||||
+ stage2_string = kernel_arguments.get("stage2")
|
||||
+
|
||||
+ if not stage2_string:
|
||||
+ return None
|
||||
+
|
||||
+ try:
|
||||
+ source = SourceFactory.parse_repo_cmdline_string(stage2_string)
|
||||
+ except PayloadSourceTypeUnrecognized:
|
||||
+ log.warning("Unknown stage2 method: %s", stage2_string)
|
||||
+ return None
|
||||
+
|
||||
+ # We have HDD here because DVD ISO has inst.stage2=hd:LABEL=....
|
||||
+ # TODO: Let's return back support of inst.cdrom=<device> which should work based on the
|
||||
+ # documentation and use that as inst.stage2 parameter for Pungi
|
||||
+ if not source.is_harddrive:
|
||||
+ log.debug("Stage2 can't be used as source %s", stage2_string)
|
||||
+ return None
|
||||
+
|
||||
+ # We can ignore source.path here because DVD ISOs are not using that.
|
||||
+ stage2_device = device_tree.ResolveDevice(source.partition)
|
||||
+ log.debug("Found possible stage2 default installation source %s", stage2_device)
|
||||
+ return stage2_device
|
||||
+
|
||||
+ def _choose_installation_device(self, device_tree, devices_candidates):
|
||||
device_name = ""
|
||||
|
||||
- for dev_name in device_tree.FindOpticalMedia():
|
||||
+ for dev_name in devices_candidates:
|
||||
try:
|
||||
device_data = DeviceData.from_structure(device_tree.GetDeviceData(dev_name))
|
||||
mount(device_data.path, self._target_mount, "iso9660", "ro")
|
||||
@@ -57,7 +108,4 @@ class SetUpCdromSourceTask(SetUpMountTask):
|
||||
else:
|
||||
unmount(self._target_mount)
|
||||
|
||||
- if not device_name:
|
||||
- raise SourceSetupError("Found no CD-ROM")
|
||||
-
|
||||
return device_name
|
||||
diff --git a/pyanaconda/modules/payloads/source/utils.py b/pyanaconda/modules/payloads/source/utils.py
|
||||
index b9642a9..5030fc5 100644
|
||||
--- a/pyanaconda/modules/payloads/source/utils.py
|
||||
+++ b/pyanaconda/modules/payloads/source/utils.py
|
||||
@@ -84,10 +84,10 @@ def find_and_mount_device(device_spec, mount_point):
|
||||
device_path = "/dev/" + matches[0]
|
||||
|
||||
try:
|
||||
- # FIXME: Add back RO mounting. This was removed because we can't mount one source
|
||||
- # RW and RO at the same time. This source is also mounted by IsoChooser dialog in the
|
||||
- # SourceSpoke.
|
||||
- mount(device_path, mount_point, "auto")
|
||||
+ mount(device=device_path,
|
||||
+ mountpoint=mount_point,
|
||||
+ fstype="auto",
|
||||
+ options="defaults,ro")
|
||||
return True
|
||||
except OSError as e:
|
||||
log.error("Mount of device failed: %s", e)
|
||||
diff --git a/pyanaconda/modules/storage/devicetree/handler.py b/pyanaconda/modules/storage/devicetree/handler.py
|
||||
index 1fca6c0..453f27d 100644
|
||||
--- a/pyanaconda/modules/storage/devicetree/handler.py
|
||||
+++ b/pyanaconda/modules/storage/devicetree/handler.py
|
||||
@@ -82,16 +82,17 @@ class DeviceTreeHandler(ABC):
|
||||
msg = "Failed to tear down {}: {}".format(device_name, str(e))
|
||||
raise DeviceSetupError(msg) from None
|
||||
|
||||
- def mount_device(self, device_name, mount_point):
|
||||
+ def mount_device(self, device_name, mount_point, options):
|
||||
"""Mount a filesystem on the device.
|
||||
|
||||
:param device_name: a name of the device
|
||||
:param mount_point: a path to the mount point
|
||||
+ :param options: a string with mount options or an empty string to use defaults
|
||||
:raise: MountFilesystemError if mount fails
|
||||
"""
|
||||
device = self._get_device(device_name)
|
||||
try:
|
||||
- device.format.mount(mountpoint=mount_point)
|
||||
+ device.format.mount(mountpoint=mount_point, options=options or None)
|
||||
except FSError as e:
|
||||
msg = "Failed to mount {} at {}: {}". format(
|
||||
device_name,
|
||||
diff --git a/pyanaconda/modules/storage/devicetree/handler_interface.py b/pyanaconda/modules/storage/devicetree/handler_interface.py
|
||||
index 3839e17..2a16eb7 100644
|
||||
--- a/pyanaconda/modules/storage/devicetree/handler_interface.py
|
||||
+++ b/pyanaconda/modules/storage/devicetree/handler_interface.py
|
||||
@@ -46,14 +46,15 @@ class DeviceTreeHandlerInterface(InterfaceTemplate):
|
||||
"""
|
||||
self.implementation.teardown_device(device_name)
|
||||
|
||||
- def MountDevice(self, device_name: Str, mount_point: Str):
|
||||
+ def MountDevice(self, device_name: Str, mount_point: Str, options: Str):
|
||||
"""Mount a filesystem on the device.
|
||||
|
||||
:param device_name: a name of the device
|
||||
:param mount_point: a path to the mount point
|
||||
+ :param options: a string with mount options or an empty string to use defaults
|
||||
:raise: MountFilesystemError if mount fails
|
||||
"""
|
||||
- self.implementation.mount_device(device_name, mount_point)
|
||||
+ self.implementation.mount_device(device_name, mount_point, options)
|
||||
|
||||
def UnmountDevice(self, device_name: Str, mount_point: Str):
|
||||
"""Unmount a filesystem on the device.
|
||||
diff --git a/pyanaconda/payload/utils.py b/pyanaconda/payload/utils.py
|
||||
index e0c7d6c..eb94f79 100644
|
||||
--- a/pyanaconda/payload/utils.py
|
||||
+++ b/pyanaconda/payload/utils.py
|
||||
@@ -71,7 +71,7 @@ def mount_device(device_name, mount_point):
|
||||
:param str mount_point: a path to the mount point
|
||||
"""
|
||||
device_tree = STORAGE.get_proxy(DEVICE_TREE)
|
||||
- device_tree.MountDevice(device_name, mount_point)
|
||||
+ device_tree.MountDevice(device_name, mount_point, "ro")
|
||||
|
||||
|
||||
def unmount_device(device_name, mount_point):
|
||||
diff --git a/tests/nosetests/pyanaconda_tests/module_device_tree_test.py b/tests/nosetests/pyanaconda_tests/module_device_tree_test.py
|
||||
index 33b06e8..838c70e 100644
|
||||
--- a/tests/nosetests/pyanaconda_tests/module_device_tree_test.py
|
||||
+++ b/tests/nosetests/pyanaconda_tests/module_device_tree_test.py
|
||||
@@ -582,12 +582,29 @@ class DeviceTreeInterfaceTestCase(unittest.TestCase):
|
||||
self._add_device(StorageDevice("dev1", fmt=get_format("ext4")))
|
||||
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
- self.interface.MountDevice("dev1", d)
|
||||
- mount.assert_called_once_with(mountpoint=d)
|
||||
+ self.interface.MountDevice("dev1", d, "")
|
||||
+ mount.assert_called_once_with(mountpoint=d, options=None)
|
||||
|
||||
mount.side_effect = FSError("Fake error.")
|
||||
with self.assertRaises(MountFilesystemError) as cm:
|
||||
- self.interface.MountDevice("dev1", "/path")
|
||||
+ self.interface.MountDevice("dev1", "/path", "")
|
||||
+
|
||||
+ self.assertEqual(
|
||||
+ str(cm.exception), "Failed to mount dev1 at /path: Fake error."
|
||||
+ )
|
||||
+
|
||||
+ @patch.object(FS, "mount")
|
||||
+ def mount_device_with_options_test(self, mount):
|
||||
+ """Test MountDevice with options specified."""
|
||||
+ self._add_device(StorageDevice("dev1", fmt=get_format("ext4")))
|
||||
+
|
||||
+ with tempfile.TemporaryDirectory() as d:
|
||||
+ self.interface.MountDevice("dev1", d, "ro,auto")
|
||||
+ mount.assert_called_once_with(mountpoint=d, options="ro,auto")
|
||||
+
|
||||
+ mount.side_effect = FSError("Fake error.")
|
||||
+ with self.assertRaises(MountFilesystemError) as cm:
|
||||
+ self.interface.MountDevice("dev1", "/path", "ro,auto")
|
||||
|
||||
self.assertEqual(
|
||||
str(cm.exception), "Failed to mount dev1 at /path: Fake error."
|
||||
diff --git a/tests/nosetests/pyanaconda_tests/module_source_cdrom_test.py b/tests/nosetests/pyanaconda_tests/module_source_cdrom_test.py
|
||||
index 386322d..4c964a7 100644
|
||||
--- a/tests/nosetests/pyanaconda_tests/module_source_cdrom_test.py
|
||||
+++ b/tests/nosetests/pyanaconda_tests/module_source_cdrom_test.py
|
||||
@@ -124,6 +124,8 @@ class CdromSourceTestCase(unittest.TestCase):
|
||||
|
||||
class CdromSourceSetupTaskTestCase(unittest.TestCase):
|
||||
|
||||
+ # TODO: To avoid so much patching it would be great to split tests to parts and test those
|
||||
+
|
||||
mount_location = "/mnt/put-cdrom-here"
|
||||
|
||||
def setup_install_source_task_name_test(self):
|
||||
@@ -156,8 +158,15 @@ class CdromSourceSetupTaskTestCase(unittest.TestCase):
|
||||
device_tree.FindOpticalMedia = Mock()
|
||||
device_tree.FindOpticalMedia.return_value = [dev.name for dev in devices]
|
||||
|
||||
+ def _find_device_by_name(name):
|
||||
+ for dev in devices:
|
||||
+ if dev.name == name:
|
||||
+ return DeviceData.to_structure(dev)
|
||||
+
|
||||
+ return None
|
||||
+
|
||||
device_tree.GetDeviceData = Mock()
|
||||
- device_tree.GetDeviceData.side_effect = [DeviceData.to_structure(dev) for dev in devices]
|
||||
+ device_tree.GetDeviceData.side_effect = _find_device_by_name
|
||||
|
||||
return device_tree
|
||||
|
||||
@@ -172,42 +181,261 @@ class CdromSourceSetupTaskTestCase(unittest.TestCase):
|
||||
This matches the logic in tested method.
|
||||
"""
|
||||
for n in range(num_called):
|
||||
- self.assertIn(
|
||||
- call("test{}".format(n)),
|
||||
- device_tree_mock.GetDeviceData.mock_calls
|
||||
- )
|
||||
- self.assertIn(
|
||||
- call("/dev/cdrom-test{}".format(n), self.mount_location, "iso9660", "ro"),
|
||||
- mount_mock.mock_calls
|
||||
- )
|
||||
+ self._check_if_device_was_tried(device_tree_mock,
|
||||
+ mount_mock,
|
||||
+ "test{}".format(n))
|
||||
|
||||
for n in range(num_called, num_called + num_untouched):
|
||||
- self.assertNotIn(
|
||||
- call("test{}".format(n)),
|
||||
- device_tree_mock.GetDeviceData.mock_calls
|
||||
- )
|
||||
- self.assertNotIn(
|
||||
- call("/dev/cdrom-test{}".format(n), self.mount_location, "iso9660", "ro"),
|
||||
- mount_mock.mock_calls
|
||||
- )
|
||||
+ self._check_if_device_was_not_tried(device_tree_mock,
|
||||
+ mount_mock,
|
||||
+ "test{}".format(n))
|
||||
|
||||
self.assertEqual(device_tree_mock.GetDeviceData.call_count, num_called)
|
||||
self.assertEqual(mount_mock.call_count, num_called)
|
||||
|
||||
+ def _check_if_device_was_tried(self,
|
||||
+ device_tree_mock,
|
||||
+ mount_mock,
|
||||
+ device_name):
|
||||
+ self.assertIn(
|
||||
+ call(device_name),
|
||||
+ device_tree_mock.GetDeviceData.mock_calls
|
||||
+ )
|
||||
+
|
||||
+ self.assertIn(
|
||||
+ call("/dev/cdrom-{}".format(device_name), self.mount_location, "iso9660", "ro"),
|
||||
+ mount_mock.mock_calls
|
||||
+ )
|
||||
+
|
||||
+ def _check_if_device_was_not_tried(self,
|
||||
+ device_tree_mock,
|
||||
+ mount_mock,
|
||||
+ device_name):
|
||||
+ self.assertNotIn(
|
||||
+ call(device_name),
|
||||
+ device_tree_mock.GetDeviceData.mock_calls
|
||||
+ )
|
||||
+
|
||||
+ self.assertNotIn(
|
||||
+ call("/dev/cdrom-{}".format(device_name), self.mount_location, "iso9660", "ro"),
|
||||
+ mount_mock.mock_calls
|
||||
+ )
|
||||
+
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.kernel_arguments")
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.is_valid_install_disk")
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.unmount")
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.mount")
|
||||
+ @patch_dbus_get_proxy
|
||||
+ def priority_stage2_cdrom_test(self,
|
||||
+ proxy_getter,
|
||||
+ mount_mock,
|
||||
+ unmount_mock,
|
||||
+ valid_mock,
|
||||
+ kernel_arguments_mock):
|
||||
+ """Test CD-ROM Source setup installation source task run - prioritize inst.stage2 CD-ROMs.
|
||||
+
|
||||
+ Add valid stage2 CDROM device and it has to be tested first.
|
||||
+ """
|
||||
+ kernel_arguments_mock.get.return_value = "hd:LABEL=my-cool-dvd"
|
||||
+ device_tree = self.set_up_device_tree(2)
|
||||
+ device_tree.ResolveDevice.return_value = "test1"
|
||||
+ proxy_getter.return_value = device_tree
|
||||
+ valid_mock.return_value = True
|
||||
+
|
||||
+ task = SetUpCdromSourceTask(self.mount_location)
|
||||
+ result = task.run()
|
||||
+
|
||||
+ # Only one device was checked
|
||||
+ device_tree.ResolveDevice.assert_called_once_with("LABEL=my-cool-dvd")
|
||||
+
|
||||
+ self._check_if_device_was_tried(device_tree, mount_mock, "test1")
|
||||
+ self._check_if_device_was_not_tried(device_tree, mount_mock, "test0")
|
||||
+
|
||||
+ # First device (stage2 device) is valid one
|
||||
+ valid_mock.assert_called_once()
|
||||
+
|
||||
+ # First device works so no unmount is called here
|
||||
+ unmount_mock.assert_not_called()
|
||||
+
|
||||
+ # Test device name returned
|
||||
+ self.assertEqual(result, "test1")
|
||||
+
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.kernel_arguments")
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.is_valid_install_disk")
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.unmount")
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.mount")
|
||||
+ @patch_dbus_get_proxy
|
||||
+ def priority_stage2_unrecognized_source_cdrom_test(self,
|
||||
+ proxy_getter,
|
||||
+ mount_mock,
|
||||
+ unmount_mock,
|
||||
+ valid_mock,
|
||||
+ kernel_arguments_mock):
|
||||
+ """Test CD-ROM Source setup installation source task run - unrecognized stage2 source.
|
||||
+
|
||||
+ This should not happen but when we have the code there let's check it.
|
||||
+ """
|
||||
+ kernel_arguments_mock.get.return_value = "wrong source!"
|
||||
+ device_tree = self.set_up_device_tree(1)
|
||||
+ proxy_getter.return_value = device_tree
|
||||
+ valid_mock.return_value = True
|
||||
+
|
||||
+ task = SetUpCdromSourceTask(self.mount_location)
|
||||
+ result = task.run()
|
||||
+
|
||||
+ device_tree.ResolveDevice.assert_not_called()
|
||||
+
|
||||
+ # 1/2 devices tried, 1/2 untried
|
||||
+ self.assert_resolve_and_mount_calls(device_tree, mount_mock, 1, 1)
|
||||
+
|
||||
+ # Only first was mounted
|
||||
+ self.assertEqual(valid_mock.call_count, 1)
|
||||
+
|
||||
+ # First device was used no unmount should be called
|
||||
+ unmount_mock.assert_not_called()
|
||||
+
|
||||
+ # Test device name returned
|
||||
+ self.assertEqual(result, "test0")
|
||||
+
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.kernel_arguments")
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.is_valid_install_disk")
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.unmount")
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.mount")
|
||||
+ @patch_dbus_get_proxy
|
||||
+ def priority_stage2_not_hdd_source_cdrom_test(self,
|
||||
+ proxy_getter,
|
||||
+ mount_mock,
|
||||
+ unmount_mock,
|
||||
+ valid_mock,
|
||||
+ kernel_arguments_mock):
|
||||
+ """Test CD-ROM Source setup installation source task run - stage2 is not HDD source.
|
||||
+
|
||||
+ We are testing HDD because DVD ISOs are created with inst.stage2=hd: . We want to change
|
||||
+ this behavior on master so let's change this test too then.
|
||||
+
|
||||
+ TODO: Change this test when DVD ISOs will use cdrom:<device> instead of inst.stage2=hd:...
|
||||
+ """
|
||||
+ kernel_arguments_mock.get.return_value = "nfs:test.org:/super/cool/path"
|
||||
+ device_tree = self.set_up_device_tree(1)
|
||||
+ proxy_getter.return_value = device_tree
|
||||
+ valid_mock.return_value = True
|
||||
+
|
||||
+ task = SetUpCdromSourceTask(self.mount_location)
|
||||
+ result = task.run()
|
||||
+
|
||||
+ device_tree.ResolveDevice.assert_not_called()
|
||||
+
|
||||
+ # 1/2 devices tried, 1/2 untried
|
||||
+ self.assert_resolve_and_mount_calls(device_tree, mount_mock, 1, 1)
|
||||
+
|
||||
+ # Only first was mounted
|
||||
+ self.assertEqual(valid_mock.call_count, 1)
|
||||
+
|
||||
+ # First device was used no unmount should be called
|
||||
+ unmount_mock.assert_not_called()
|
||||
+
|
||||
+ # Test device name returned
|
||||
+ self.assertEqual(result, "test0")
|
||||
+
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.kernel_arguments")
|
||||
@patch("pyanaconda.modules.payloads.source.cdrom.initialization.is_valid_install_disk")
|
||||
@patch("pyanaconda.modules.payloads.source.cdrom.initialization.unmount")
|
||||
@patch("pyanaconda.modules.payloads.source.cdrom.initialization.mount")
|
||||
@patch_dbus_get_proxy
|
||||
- def choose_from_multiple_cdroms_test(self, proxy_getter, mount_mock, unmount_mock, valid_mock):
|
||||
+ def priority_stage2_cant_be_resolved_source_cdrom_test(self,
|
||||
+ proxy_getter,
|
||||
+ mount_mock,
|
||||
+ unmount_mock,
|
||||
+ valid_mock,
|
||||
+ kernel_arguments_mock):
|
||||
+ """Test CD-ROM Source setup installation source task run - can't resolve stage2 device.
|
||||
+
|
||||
+ Stage2 device can't be resolved. This should not happen but let's make sure the code works.
|
||||
+ """
|
||||
+ kernel_arguments_mock.get.return_value = "hd:LABEL=my-cool-dvd"
|
||||
+ device_tree = self.set_up_device_tree(1)
|
||||
+ proxy_getter.return_value = device_tree
|
||||
+ # When device can't be resolved it returns an empty string.
|
||||
+ device_tree.ResolveDevice.return_value = ""
|
||||
+ valid_mock.return_value = True
|
||||
+
|
||||
+ task = SetUpCdromSourceTask(self.mount_location)
|
||||
+ result = task.run()
|
||||
+
|
||||
+ self._check_if_device_was_not_tried(device_tree, mount_mock, "")
|
||||
+
|
||||
+ # 1/2 devices tried, 1/2 untried
|
||||
+ self.assert_resolve_and_mount_calls(device_tree, mount_mock, 1, 1)
|
||||
+
|
||||
+ # Only first was mounted
|
||||
+ self.assertEqual(valid_mock.call_count, 1)
|
||||
+
|
||||
+ # First device was used no unmount should be called
|
||||
+ unmount_mock.assert_not_called()
|
||||
+
|
||||
+ # Test device name returned
|
||||
+ self.assertEqual(result, "test0")
|
||||
+
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.kernel_arguments")
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.is_valid_install_disk")
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.unmount")
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.mount")
|
||||
+ @patch_dbus_get_proxy
|
||||
+ def priority_stage2_not_optical_media_cdrom_test(self,
|
||||
+ proxy_getter,
|
||||
+ mount_mock,
|
||||
+ unmount_mock,
|
||||
+ valid_mock,
|
||||
+ kernel_arguments_mock):
|
||||
+ """Test CD-ROM Source setup installation source task run - stage2 is not optical media.
|
||||
+
|
||||
+ We should not pick stage2 device if it is not an optical_media which means type iso9660.
|
||||
+ """
|
||||
+ kernel_arguments_mock.get.return_value = "hd:LABEL=correct-device"
|
||||
+ device_tree = self.set_up_device_tree(1)
|
||||
+ device_tree.ResolveDevice.return_value = "not-optical-media"
|
||||
+ proxy_getter.return_value = device_tree
|
||||
+ valid_mock.return_value = True
|
||||
+
|
||||
+ task = SetUpCdromSourceTask(self.mount_location)
|
||||
+ result = task.run()
|
||||
+
|
||||
+ device_tree.ResolveDevice.assert_called_once_with("LABEL=correct-device")
|
||||
+
|
||||
+ self._check_if_device_was_not_tried(device_tree, mount_mock, "correct-device")
|
||||
+
|
||||
+ # 1/2 devices tried, 1/2 untried
|
||||
+ self.assert_resolve_and_mount_calls(device_tree, mount_mock, 1, 1)
|
||||
+
|
||||
+ # Only first was mounted
|
||||
+ self.assertEqual(valid_mock.call_count, 1)
|
||||
+
|
||||
+ # First device was used no unmount should be called
|
||||
+ unmount_mock.assert_not_called()
|
||||
+
|
||||
+ # Test device name returned
|
||||
+ self.assertEqual(result, "test0")
|
||||
+
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.kernel_arguments")
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.is_valid_install_disk")
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.unmount")
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.mount")
|
||||
+ @patch_dbus_get_proxy
|
||||
+ def choose_from_multiple_cdroms_test(self,
|
||||
+ proxy_getter,
|
||||
+ mount_mock,
|
||||
+ unmount_mock,
|
||||
+ valid_mock,
|
||||
+ kernel_arguments_mock):
|
||||
"""Test CD-ROM Source setup installation source task run - choice from multiple CD-ROMs.
|
||||
|
||||
Fake four CD-ROM devices: First fails to mount, second has nothing useful, third has what
|
||||
we want so is left mounted, fourth is entirely skipped.
|
||||
The other two tests below are needed only to test the exit when nothing is found.
|
||||
"""
|
||||
+ kernel_arguments_mock.get.return_value = None
|
||||
device_tree = self.set_up_device_tree(4)
|
||||
proxy_getter.return_value = device_tree
|
||||
-
|
||||
mount_mock.side_effect = \
|
||||
[PayloadSetupError("Mocked failure"), DEFAULT, DEFAULT, DEFAULT]
|
||||
|
||||
@@ -231,18 +459,24 @@ class CdromSourceSetupTaskTestCase(unittest.TestCase):
|
||||
# Test device name returned
|
||||
self.assertEqual(result, "test2")
|
||||
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.kernel_arguments")
|
||||
@patch("pyanaconda.modules.payloads.source.cdrom.initialization.is_valid_install_disk")
|
||||
@patch("pyanaconda.modules.payloads.source.cdrom.initialization.unmount")
|
||||
@patch("pyanaconda.modules.payloads.source.cdrom.initialization.mount")
|
||||
@patch_dbus_get_proxy
|
||||
- def failure_to_mount_test(self, proxy_getter, mount_mock, unmount_mock, valid_mock):
|
||||
+ def failure_to_mount_test(self,
|
||||
+ proxy_getter,
|
||||
+ mount_mock,
|
||||
+ unmount_mock,
|
||||
+ valid_mock,
|
||||
+ kernel_arguments_mock):
|
||||
"""Test CD-ROM Source setup installation source task run - mount failure.
|
||||
|
||||
Mocks one disk which fails to mount, expect exception.
|
||||
"""
|
||||
+ kernel_arguments_mock.get.return_value = None
|
||||
device_tree = self.set_up_device_tree(1)
|
||||
proxy_getter.return_value = device_tree
|
||||
-
|
||||
mount_mock.side_effect = PayloadSetupError("Mocked failure")
|
||||
valid_mock.return_value = True
|
||||
|
||||
@@ -258,18 +492,24 @@ class CdromSourceSetupTaskTestCase(unittest.TestCase):
|
||||
# exception happened due to no disk
|
||||
self.assertEqual(str(cm.exception), "Found no CD-ROM")
|
||||
|
||||
+ @patch("pyanaconda.modules.payloads.source.cdrom.initialization.kernel_arguments")
|
||||
@patch("pyanaconda.modules.payloads.source.cdrom.initialization.is_valid_install_disk")
|
||||
@patch("pyanaconda.modules.payloads.source.cdrom.initialization.unmount")
|
||||
@patch("pyanaconda.modules.payloads.source.cdrom.initialization.mount")
|
||||
@patch_dbus_get_proxy
|
||||
- def no_cdrom_with_valid_source_test(self, proxy_getter, mount_mock, unmount_mock, valid_mock):
|
||||
+ def no_cdrom_with_valid_source_test(self,
|
||||
+ proxy_getter,
|
||||
+ mount_mock,
|
||||
+ unmount_mock,
|
||||
+ valid_mock,
|
||||
+ kernel_arguments_mock):
|
||||
"""Test CD-ROM Source setup installation source task run - no valid source CD-ROMs.
|
||||
|
||||
Mocks one CD-ROM device which has nothing useful, expect exception.
|
||||
"""
|
||||
+ kernel_arguments_mock.get.return_value = None
|
||||
device_tree = self.set_up_device_tree(1)
|
||||
proxy_getter.return_value = device_tree
|
||||
-
|
||||
valid_mock.return_value = False
|
||||
|
||||
with self.assertRaises(SourceSetupError) as cm:
|
||||
--
|
||||
2.23.0
|
||||
|
||||
187
anaconda.spec
187
anaconda.spec
@ -1,162 +1,55 @@
|
||||
%define _empty_manifest_terminate_build 0
|
||||
Name: anaconda
|
||||
Version: 33.19
|
||||
Release: 49
|
||||
Version: 36.16.5
|
||||
Release: 1
|
||||
Summary: Graphical system installer
|
||||
License: GPLv2+ and MIT
|
||||
URL: http://fedoraproject.org/wiki/Anaconda
|
||||
Source0: https://github.com/rhinstaller/anaconda/archive/%{name}-%{version}.tar.bz2
|
||||
Source0: https://github.com/rhinstaller/%{name}/releases/download/%{name}-%{version}-1/%{name}-%{version}.tar.bz2
|
||||
Source1: openeuler.conf
|
||||
Source2: euleros.conf
|
||||
Source3: hce.conf
|
||||
|
||||
Patch6000: Fix-hiding-of-network-device-activation-switch.patch
|
||||
|
||||
Patch9000: add-passwd-policy.patch
|
||||
Patch9001: fix-hostname-info.patch
|
||||
Patch9002: disable-set-passwd-without-confirmation.patch
|
||||
Patch9003: bugfix-logo-display-in-low-screen-resolution.patch
|
||||
Patch9004: make-name-not-force-to-uppercase.patch
|
||||
Patch9005: bugfix-GUI-nfs-unknown-error.patch
|
||||
Patch9006: hide-help-button.patch
|
||||
Patch9007: modify-interface-is-extended-in-Chinese-mode.patch
|
||||
Patch9008: remove-vender-issue-in-netdev.patch
|
||||
Patch9009: modify-arguments-parsing.patch
|
||||
Patch9011: disable-product-name-in-welcome-is-uppercase.patch
|
||||
Patch9012: modify-default-timezone.patch
|
||||
Patch9013: modify-network-hostname-dot-illegal.patch
|
||||
Patch9014: disable-ssh-login-checkbox.patch
|
||||
Patch9016: bugfix-fix-password-policy.patch
|
||||
Patch9018: disable-disk-encryption.patch
|
||||
Patch9019: bugfix-set-up-LD_PRELOAD-for-the-Storage-and-Services-module.patch
|
||||
Patch9020: bugfix-Propagate-a-lazy-proxy-of-the-storage-model.patch
|
||||
|
||||
Patch6001: anaconda-Fix-stage2-as-default-sources.patch
|
||||
Patch6002: anaconda-Allow-to-detect-devices-with-the-iso9660-file-system.patch
|
||||
Patch6003: bugfix-do-not-test-if-repo-is-valid-based-on-treeinfo-file.patch
|
||||
Patch6004: bugfix-move-verify-valid-installtree-to-source-module-utils.patch
|
||||
Patch6005: bugfix-add-tests-for-verify-valid-installtree-function.patch
|
||||
Patch6006: bugfix-rename-function-for-a-simple-check-for-DNF-repository.patch
|
||||
|
||||
Patch9023: bugfix-add-dnf-transaction-timeout.patch
|
||||
|
||||
Patch6007: fix-0-storage-devices-selected.patch
|
||||
Patch6008: fix-remove-unknow-partition-is-sda-failed.patch
|
||||
Patch6009: use-modinfo-to-check-ko-before-modprobe.patch
|
||||
Patch6010: ntp-servers-improve-001-Create-a-new-DBus-structure-for-time-sources.patch
|
||||
Patch6011: ntp-servers-improve-002-Use-the-structure-for-time-sources-in-ntp-py.patch
|
||||
Patch6012: ntp-servers-improve-003-Use-the-structure-for-time-sources-in-the-Timezone-module.patch
|
||||
Patch6013: ntp-servers-improve-004-Use-the-structure-for-time-sources-in-anaconda-py.patch
|
||||
Patch6014: ntp-servers-improve-005-Use-the-structure-for-time-sources-in-network-py.patch
|
||||
Patch6015: ntp-servers-improve-006-Add-support-for-the-NTP-server-status-cache.patch
|
||||
Patch6016: ntp-servers-improve-007-Add-support-for-generating-a-summary-of-the-NTP-servers.patch
|
||||
Patch6017: ntp-servers-improve-008-Use-the-structure-for-time-sources-in-TUI.patch
|
||||
Patch6018: ntp-servers-improve-009-Use-the-structure-for-time-sources-in-GUI.patch
|
||||
Patch6019: ntp-servers-improve-010-Add-support-for-the-timesource-kickstart-command.patch
|
||||
|
||||
Patch9024: Change-length-limit-of-hostname-from-255-to-64.patch
|
||||
Patch9025: Change-topbar-background-size.patch
|
||||
|
||||
Patch6020: bugfix-Schedule-timed-actions-with-the-right-selector-18516.patch
|
||||
Patch6021: bugfix-Reset-the-state-of-the-custom-partitioning-spoke.patch
|
||||
Patch6022: bugfix-Fix-regression-reading-kernel-list-when-collecting-c.patch
|
||||
Patch6023: bugfix-Fix-more-SElinux-contexts.patch
|
||||
Patch6024: bugfix-Fix-issue-when-NFS-path-is-pointing-directly-to-ISO-.patch
|
||||
Patch6025: bugfix-Create-the-initial-storage-model-during-the-initiali.patch
|
||||
Patch6026: bugfix-Always-specify-the-boot-disk.patch
|
||||
Patch6027: bugfix-Fix-passing-of-arguments-when-creating-dracut-argume.patch
|
||||
Patch6028: bugfix-Reconfigure-DNF-payload-after-options-are-set.patch
|
||||
Patch6029: bugfix-Only-pass-one-initrd-image-to-kexec.patch
|
||||
Patch6030: bugfix-Fix-creating-cached-LVs-on-encrypted-PVs.patch
|
||||
Patch6031: bugfix-Run-actions-of-the-Resize-dialog-in-the-reversed-ord.patch
|
||||
Patch6032: bugfix-Reload-treeinfo-repositories-on-every-payload-reset.patch
|
||||
Patch6033: bugfix-Remove-treeinfo-repositories-instead-of-disabling.patch
|
||||
Patch6034: bugfix-Fix-crash-on-first-entering-of-source-spoke.patch
|
||||
Patch6035: bugfix-Keep-treeinfo-repositories-disabled-after-payload-re.patch
|
||||
Patch6036: bugfix-Fix-issue-that-treeinfo-repositories-were-never-disa.patch
|
||||
Patch6037: bugfix-Fix-kickstart-file-error-with-user-groups.patch
|
||||
Patch6038: bugfix-Create-ssh-user-using-only-existing-fields-1860058.patch
|
||||
Patch6039: bugfix-Automatically-break-lines-in-labels-in-software-sele.patch
|
||||
Patch6040: bugfix-Reset-the-RAID-level-of-the-device-request-1828092.patch
|
||||
Patch6041: bugfix-Change-keyboard-ordering-to-US-layout-first-native-s.patch
|
||||
Patch6042: bugfix-Handle-exceptions-from-threads-without-new-instances.patch
|
||||
Patch6043: bugfix-network-fix-configuration-of-virtual-devices-by-boot.patch
|
||||
Patch6044: bugfix-network-do-not-try-to-activate-connection-that-has-n.patch
|
||||
Patch6045: bugfix-network-add-timeout-for-synchronous-activation-of-a-.patch
|
||||
Patch6046: bugfix-Fix-traceback-when-removing-additional-repository.patch
|
||||
Patch6047: bugfix-network-do-not-crash-when-updating-a-connection-with.patch
|
||||
Patch6048: bugfix-Do-not-mount-as-RW-in-Dracut.patch
|
||||
Patch6049: bugfix-The-underline-character-should-not-be-displayed.patch
|
||||
Patch6050: bugfix-Recognize-systemd.unit-anaconda.target-in-anaconda-g.patch
|
||||
Patch6051: bugfix-Always-clear-treeinfo-metadata-1872056.patch
|
||||
Patch6052: bugfix-Apply-onboot-policy-even-when-network-was-configured.patch
|
||||
Patch6053: bugfix-network-fix-parsing-of-hostname-from-ip-if-mac-is-de.patch
|
||||
Patch6054: bugfix-Don-t-generate-container-data-for-non-container-devi.patch
|
||||
Patch6055: bugfix-Differentiate-between-RAID-levels-of-a-device-and-it.patch
|
||||
Patch6056: bugfix-Show-warning-message-when-entered-size-is-not-valid.patch
|
||||
Patch6057: bugfix-Add-the-DBus-method-IsDeviceShrinkable-1875677.patch
|
||||
Patch6058: bugfix-Check-if-original-partitions-are-mounted-too.patch
|
||||
Patch6059: bugfix-network-get-hwadddr-when-binding-to-mac-more-robustl.patch
|
||||
Patch6060: bugfix-Fix-the-combo-box-for-an-URL-type-of-additional-repo.patch
|
||||
Patch6061: bugfix-Never-mount-partitions-on-a-disk-with-the-iso9660-fi.patch
|
||||
Patch6062: bugfix-Add-missing-make-BuildRequires.patch
|
||||
Patch6063: bugfix-Allow-to-format-selected-DASDs.patch
|
||||
Patch6064: bugfix-Add-selinux-0-boot-parameter-when-SELinux-is-set-to-.patch
|
||||
Patch6065: bugfix-Root-password-is-mandatory-if-there-is-not-admin-use.patch
|
||||
Patch6066: bugfix-Fix-traceback-when-starting-installation-with-inst.c.patch
|
||||
Patch6067: bugfix-Fix-checking-ssl-certificate-for-metadata-1745064.patch
|
||||
Patch6068: bugfix-Fix-error-in-initrd-shift-count-out-of-range.patch
|
||||
Patch6069: bugfix-Fix-the-logic-for-enabling-latest-updates.patch
|
||||
Patch6070: bugfix-Don-t-enter-spokes-after-we-leave-the-Summary-hub.patch
|
||||
Patch6071: bugfix-do-not-mount-dbus-source.patch
|
||||
Patch6072: fix-xorg-timeout-and-throw-exception.patch
|
||||
Patch6073: bugfix-Fix-issue-when-ns_info-cannot-be-retrieved-for-NVDim.patch
|
||||
Patch6074: bugfix-Fix-SECTION-headers-in-docstrings.patch
|
||||
Patch6075: change-inst-repo-default-value.patch
|
||||
Patch6076: delete-datezone-map.patch
|
||||
|
||||
Patch6077: backport-fix-boot-options-generated-by-dracut-module.patch
|
||||
Patch9027: bugfix-remove-flatpack-support.patch
|
||||
Patch9028: Change-sidebar-background-size.patch
|
||||
Patch6078: bugfix-Cancel-planned-manual-update-of-system-time-on-turni.patch
|
||||
Patch9029: support-use-sm3-crypt-user-password.patch
|
||||
Patch6079: backport-remove-authconfig-support.patch
|
||||
Patch6080: backport-change-the-grub2-user-cfg-permission-from-0700-to-0600.patch
|
||||
Patch6081: bugfix-change-the-startup-mode-of-do_transaction-sub-proces.patch
|
||||
Patch6082: Support-configuration-of-additional-boot-arguments.patch
|
||||
|
||||
Patch6083: backport-revert-Set-default-entry-to-the-BLS-id-instead-of-th.patch
|
||||
Patch6084: bugfix-Solve-the-problem-that-the-circular-loading-progress-bar-does-not-rotate.patch
|
||||
%ifarch sw_64
|
||||
Patch6085: anaconda-33.19.sw.patch
|
||||
%endif
|
||||
%ifarch loongarch64
|
||||
Patch6086: 0001-add-loongarch-support-for-anaconda-33.19.patch
|
||||
%endif
|
||||
Patch9001: bugfix-GUI-nfs-unknown-error.patch
|
||||
Patch9002: bugfix-set-up-LD_PRELOAD-for-the-Storage-and-Services-module.patch
|
||||
Patch9003: bugfix-Solve-the-problem-that-the-circular-loading-progress-bar-does-not-rotate.patch
|
||||
Patch9004: change-inst-repo-default-value.patch
|
||||
Patch9005: disable-disk-encryption.patch
|
||||
Patch9006: disable-ssh-login-checkbox.patch
|
||||
Patch9007: fix-hostname-info.patch
|
||||
Patch9008: hide-help-button.patch
|
||||
Patch9009: modify-interface-is-extended-in-Chinese-mode.patch
|
||||
Patch9010: modify-timezone-and-delete-datezone-map.patch
|
||||
Patch9011: remove-vender-issue-in-netdev.patch
|
||||
Patch9012: Support-configuration-of-additional-boot-arguments.patch
|
||||
Patch9013: support-use-sm3-crypt-user-password.patch
|
||||
|
||||
%define dasbusver 1.3
|
||||
%define dbusver 1.2.3
|
||||
%define dnfver 3.6.0
|
||||
%define dracutver 034-7
|
||||
%define gettextver 0.19.8
|
||||
%define gtk3ver 3.22.17
|
||||
%define isomd5sum 1.0.10
|
||||
%define langtablever 0.0.49
|
||||
%define isomd5sumver 1.0.10
|
||||
%define langtablever 0.0.54
|
||||
%define libarchivever 3.0.4
|
||||
%define libblockdevver 2.1
|
||||
%define libxklavierver 5.4
|
||||
%define mehver 0.23-1
|
||||
%define nmver 1.0
|
||||
%define pykickstartver 3.27-1
|
||||
%define pykickstartver 3.32-1
|
||||
%define pypartedver 2.5-2
|
||||
%define rpmver 4.10.0
|
||||
%define pythonblivetver 1:3.4.0-1
|
||||
%define rpmver 4.15.0
|
||||
%define simplelinever 1.1-1
|
||||
%define utillinuxver 2.15.1
|
||||
%define dasbusver 0.4
|
||||
BuildRequires: python3-pygments
|
||||
|
||||
BuildRequires: audit-libs-devel libtool gettext-devel >= %{gettextver} gtk3-devel >= %{gtk3ver}
|
||||
BuildRequires: gtk-doc gtk3-devel-docs >= %{gtk3ver} glib2-doc gobject-introspection-devel
|
||||
BuildRequires: glade-devel libgnomekbd-devel libxklavier-devel >= %{libxklavierver} pango-devel
|
||||
BuildRequires: make
|
||||
BuildRequires: python3-kickstart >= %{pykickstartver} python3-devel systemd
|
||||
BuildRequires: rpm-devel >= %{rpmver} libarchive-devel >= %{libarchivever} gdk-pixbuf2-devel
|
||||
BuildRequires: libxml2
|
||||
@ -164,16 +57,14 @@ BuildRequires: gsettings-desktop-schemas metacity
|
||||
|
||||
Requires: anaconda-core = %{version}-%{release}
|
||||
Requires: anaconda-tui = %{version}-%{release}
|
||||
Requires: libblockdev-plugins-all >= %{libblockdevver} realmd isomd5sum >= %{isomd5sum}
|
||||
Requires: libblockdev-plugins-all >= %{libblockdevver} realmd isomd5sum >= %{isomd5sumver}
|
||||
Requires: kexec-tools createrepo_c tmux gdb rsync python3-meh-gui >= %{mehver}
|
||||
Requires: adwaita-icon-theme python3-kickstart
|
||||
Requires: tigervnc-server-minimal libxklavier >= %{libxklavierver} libgnomekbd
|
||||
Requires: nm-connection-editor keybinder3 system-logos
|
||||
Requires: python3
|
||||
%ifarch %{ix86} x86_64
|
||||
BuildRequires: desktop-file-utils
|
||||
Requires: zenity
|
||||
%endif
|
||||
|
||||
Provides: anaconda-gui = %{version}-%{release}
|
||||
Obsoletes: anaconda-gui < %{version}-%{release}
|
||||
@ -189,16 +80,21 @@ The anaconda package is a metapackage for the Anaconda installer.
|
||||
|
||||
%package core
|
||||
Summary: Core of the Anaconda installer
|
||||
Requires: python3-libs python3-dnf >= %{dnfver} python3-blivet >= 1:3.2.2-1
|
||||
Requires: python3-libs python3-dnf >= %{dnfver} python3-blivet >= %{pythonblivetver}
|
||||
Requires: python3-blockdev >= %{libblockdevver} rpm-python3 >= %{rpmver} python3-productmd
|
||||
Requires: libreport-anaconda >= 2.0.21-1 libselinux-python3 python3-meh >= %{mehver}
|
||||
Requires: python3-pyparted >= %{pypartedver} python3-requests python3-requests-file
|
||||
Requires: python3-requests-ftp python3-kickstart >= %{pykickstartver}
|
||||
Requires: python3-langtable >= %{langtablever} util-linux >= %{utillinuxver} python3-gobject-base
|
||||
Requires: python3-dbus python3-pwquality python3-systemd python3-dasbus >= %{dasbusver}
|
||||
Requires: python3-packaging
|
||||
Requires: cracklib-dicts python3-pytz teamd NetworkManager >= %{nmver} NetworkManager-libnm >= %{nmver}
|
||||
Requires: NetworkManager-team dhclient kbd chrony python3-ntplib systemd python3-pid
|
||||
Requires: NetworkManager-team kbd chrony systemd python3-pid
|
||||
Requires: python3-ordered-set >= 2.0.0 glibc-langpack-en dbus-daemon
|
||||
Requires: systemd-resolved
|
||||
# Required by the systemd service anaconda-fips.
|
||||
Requires: crypto-policies
|
||||
Requires: /usr/bin/update-crypto-policies
|
||||
# required because of the rescue mode and VNC question
|
||||
Requires: anaconda-tui = %{version}-%{release}
|
||||
Provides: anaconda-images = %{version}-%{release}
|
||||
@ -210,10 +106,7 @@ Obsoletes: booty <= 0.107-1
|
||||
# Ensure it's not possible for a version of grubby to be installed
|
||||
# that doesn't work with btrfs subvolumes correctly...
|
||||
Conflicts: grubby < 8.40-10
|
||||
|
||||
%ifarch %{ix86} x86_64
|
||||
Requires: usermode
|
||||
%endif
|
||||
|
||||
%description core
|
||||
The anaconda-core package contains the program which was used to install your
|
||||
@ -244,7 +137,6 @@ Requires: dracut-network
|
||||
Requires: dracut-live
|
||||
Requires: xz
|
||||
Requires: python3-kickstart
|
||||
Conflicts: anaconda < %{version}-41
|
||||
|
||||
%description dracut
|
||||
The 'anaconda' dracut module handles installer-specific boot tasks and
|
||||
@ -275,17 +167,15 @@ sed -i "/^additional_arguments =*/ s/$/ crashkernel=1024M,high smmu.bypassdev=0x
|
||||
sed -i "/^additional_arguments =*/ s/$/ panic=1 vga=0x317 nohz=off smmu.bypassdev=0x1000:0x17 smmu.bypassdev=0x1000:0x15/" %{SOURCE2}
|
||||
sed -i "/^additional_arguments =*/ s/$/ panic=1 vga=0x317 nohz=off smmu.bypassdev=0x1000:0x17 smmu.bypassdev=0x1000:0x15/" %{SOURCE3}
|
||||
%endif
|
||||
install -m 0644 %{SOURCE1} %{buildroot}/%{_sysconfdir}/%{name}/product.d/
|
||||
install -m 0644 %{SOURCE2} %{buildroot}/%{_sysconfdir}/%{name}/product.d/
|
||||
install -m 0644 %{SOURCE3} %{buildroot}/%{_sysconfdir}/%{name}/product.d/
|
||||
install -m 0644 %{SOURCE1} %{buildroot}/%{_sysconfdir}/%{name}/profile.d/
|
||||
install -m 0644 %{SOURCE2} %{buildroot}/%{_sysconfdir}/%{name}/profile.d/
|
||||
install -m 0644 %{SOURCE3} %{buildroot}/%{_sysconfdir}/%{name}/profile.d/
|
||||
|
||||
|
||||
# Create an empty directory for addons
|
||||
install -d -m 0755 %{buildroot}%{_datadir}/anaconda/addons
|
||||
|
||||
%ifarch %{ix86} x86_64
|
||||
desktop-file-install --dir=%{buildroot}%{_datadir}/applications %{buildroot}%{_datadir}/applications/liveinst.desktop
|
||||
%endif
|
||||
|
||||
# If no langs found, keep going
|
||||
%find_lang %{name} || :
|
||||
@ -344,8 +234,8 @@ update-desktop-database &> /dev/null || :
|
||||
%config %{_sysconfdir}/%{name}/*
|
||||
%dir %{_sysconfdir}/%{name}/conf.d
|
||||
%config %{_sysconfdir}/%{name}/conf.d/*
|
||||
%dir %{_sysconfdir}/%{name}/product.d
|
||||
%config %{_sysconfdir}/%{name}/product.d/*
|
||||
%dir %{_sysconfdir}/%{name}/profile.d
|
||||
%config %{_sysconfdir}/%{name}/profile.d/*
|
||||
%{_sbindir}/liveinst
|
||||
%{_bindir}/liveinst
|
||||
%{_libexecdir}/liveinst-setup.sh
|
||||
@ -372,6 +262,11 @@ update-desktop-database &> /dev/null || :
|
||||
%{_prefix}/libexec/anaconda/dd_*
|
||||
|
||||
%changelog
|
||||
* Tue Nov 08 2022 sunhai <sunhai10@huawei.com> - 36.16.5-1
|
||||
- ID:NA
|
||||
- SUG:NA
|
||||
- DESC:update anaconda to 36.16.5
|
||||
|
||||
* Mon Mar 28 2022 Wenlong Zhang <zhangwenlong@loongson.cn> - 33.19-49
|
||||
- ID:NA
|
||||
- SUG:NA
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
From 7db645b89c3c68fbd116dbb8c6e6c1b4ab8eeb07 Mon Sep 17 00:00:00 2001
|
||||
From: bitcoffee <854182924@qq.com>
|
||||
Date: Tue, 2 Mar 2021 16:11:35 +0800
|
||||
Subject: [PATCH] change the grub2 user.cfg permission from 0600 to 0700
|
||||
|
||||
---
|
||||
pyanaconda/modules/storage/bootloader/grub2.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/bootloader/grub2.py b/pyanaconda/modules/storage/bootloader/grub2.py
|
||||
index add7dc97086..44b08e4dec9 100644
|
||||
--- a/pyanaconda/modules/storage/bootloader/grub2.py
|
||||
+++ b/pyanaconda/modules/storage/bootloader/grub2.py
|
||||
@@ -310,7 +310,7 @@ def write_password_config(self):
|
||||
return
|
||||
|
||||
users_file = "%s%s/%s" % (conf.target.system_root, self.config_dir, self._passwd_file)
|
||||
- header = util.open_with_perm(users_file, "w", 0o700)
|
||||
+ header = util.open_with_perm(users_file, "w", 0o600)
|
||||
# XXX FIXME: document somewhere that the username is "root"
|
||||
self._encrypt_password()
|
||||
password_line = "GRUB2_PASSWORD=" + self.encrypted_password
|
||||
@ -1,56 +0,0 @@
|
||||
From a807e0095d7c89e47735cd9caa1a19a1489165c4 Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Fri, 29 Oct 2021 15:36:40 +0800
|
||||
Subject: [PATCH] fix boot options generated by dracut module
|
||||
|
||||
Add the inst. prefix to the anaconda boot options
|
||||
|
||||
---
|
||||
dracut/parse-kickstart | 4 ++--
|
||||
tests/nosetests/dracut_tests/parse-kickstart_test.py | 4 ++--
|
||||
2 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dracut/parse-kickstart b/dracut/parse-kickstart
|
||||
index 9b55ad6..63e71de 100755
|
||||
--- a/dracut/parse-kickstart
|
||||
+++ b/dracut/parse-kickstart
|
||||
@@ -171,7 +171,7 @@ class DracutURL(Url, DracutArgsMixin):
|
||||
if self.noverifyssl:
|
||||
args.append("rd.noverifyssl")
|
||||
if self.proxy:
|
||||
- args.append("proxy=%s" % self.proxy)
|
||||
+ args.append("inst.proxy=%s" % self.proxy)
|
||||
|
||||
return "\n".join(args)
|
||||
|
||||
@@ -267,7 +267,7 @@ class DracutDisplayMode(DisplayMode, DracutArgsMixin):
|
||||
class DracutBootloader(Bootloader, DracutArgsMixin):
|
||||
def dracut_args(self, args, lineno, obj):
|
||||
if self.extlinux:
|
||||
- return "extlinux"
|
||||
+ return "inst.extlinux"
|
||||
|
||||
# FUTURE: keymap, lang... device? selinux?
|
||||
|
||||
diff --git a/tests/nosetests/dracut_tests/parse-kickstart_test.py b/tests/nosetests/dracut_tests/parse-kickstart_test.py
|
||||
index 9a5cdcd..4dd37c7 100644
|
||||
--- a/tests/nosetests/dracut_tests/parse-kickstart_test.py
|
||||
+++ b/tests/nosetests/dracut_tests/parse-kickstart_test.py
|
||||
@@ -94,7 +94,7 @@ class ParseKickstartTestCase(BaseTestCase):
|
||||
self.assertEqual(len(lines), 3, lines)
|
||||
self.assertEqual(lines[0], "inst.repo=https://host.at.foo.com/path/to/tree", lines)
|
||||
self.assertEqual(lines[1], "rd.noverifyssl", lines)
|
||||
- self.assertEqual(lines[2], "proxy=http://localhost:8123", lines)
|
||||
+ self.assertEqual(lines[2], "inst.proxy=http://localhost:8123", lines)
|
||||
|
||||
def updates_test(self):
|
||||
with tempfile.NamedTemporaryFile(mode="w+t") as ks_file:
|
||||
@@ -344,4 +344,4 @@ network --device=lo --vlanid=171 --interfacename=vlan171
|
||||
ks_file.flush()
|
||||
lines = self.execParseKickstart(ks_file.name)
|
||||
|
||||
- self.assertEqual(lines[0], "extlinux", lines)
|
||||
+ self.assertEqual(lines[0], "inst.extlinux", lines)
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,423 +0,0 @@
|
||||
From 17b8e2e895448aeae990b419036448011b6eb105 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
|
||||
Date: Fri, 9 Jul 2021 12:51:07 +0200
|
||||
Subject: [PATCH] remove authconfig support
|
||||
|
||||
Authconfig compatibility tool (from authselect-compat) will be removed from Fedora 35:
|
||||
https://fedoraproject.org/wiki/Changes/RemoveAuthselectCompatPackage
|
||||
---
|
||||
pyanaconda/core/kickstart/commands.py | 1 -
|
||||
pyanaconda/modules/security/installation.py | 35 +-------
|
||||
pyanaconda/modules/security/kickstart.py | 2 -
|
||||
pyanaconda/modules/security/security.py | 44 +--------
|
||||
.../modules/security/security_interface.py | 23 -----
|
||||
.../modules/security/test_module_security.py | 89 +------------------
|
||||
6 files changed, 6 insertions(+), 188 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/core/kickstart/commands.py b/pyanaconda/core/kickstart/commands.py
|
||||
index 3c3eed0..b3fbdff 100644
|
||||
--- a/pyanaconda/core/kickstart/commands.py
|
||||
+++ b/pyanaconda/core/kickstart/commands.py
|
||||
@@ -22,7 +22,6 @@
|
||||
# pylint:disable=unused-import
|
||||
|
||||
# Supported kickstart commands.
|
||||
-from pykickstart.commands.authconfig import F28_Authconfig as Authconfig
|
||||
from pykickstart.commands.authselect import F28_Authselect as Authselect
|
||||
from pykickstart.commands.autopart import F29_AutoPart as AutoPart
|
||||
from pykickstart.commands.autostep import FC3_AutoStep as AutoStep
|
||||
|
||||
diff --git a/pyanaconda/modules/security/installation.py b/pyanaconda/modules/security/installation.py
|
||||
index 03badc1678..9d3369f737 100644
|
||||
--- a/pyanaconda/modules/security/installation.py
|
||||
+++ b/pyanaconda/modules/security/installation.py
|
||||
@@ -33,7 +33,6 @@
|
||||
|
||||
REALM_TOOL_NAME = "realm"
|
||||
AUTHSELECT_TOOL_PATH = "/usr/bin/authselect"
|
||||
-AUTHCONFIG_TOOL_PATH = "/usr/sbin/authconfig"
|
||||
PAM_SO_PATH = "/lib/security/pam_fprintd.so"
|
||||
PAM_SO_64_PATH = "/lib64/security/pam_fprintd.so"
|
||||
|
||||
@@ -356,7 +355,7 @@ def run(self):
|
||||
def run_auth_tool(cmd, args, root, required=True):
|
||||
"""Run an authentication related tool.
|
||||
|
||||
- This generally means either authselect or the legacy authconfig tool.
|
||||
+ This generally means authselect.
|
||||
:param str cmd: path to the tool to be run
|
||||
:param list(str) args: list of arguments passed to the tool
|
||||
:param str root: a path to the root in which the tool should be run
|
||||
@@ -443,35 +442,3 @@ def run(self):
|
||||
self._authselect_options + ["--force"],
|
||||
self._sysroot
|
||||
)
|
||||
-
|
||||
-
|
||||
-class ConfigureAuthconfigTask(Task):
|
||||
- """Installation task for Authconfig configuration.
|
||||
-
|
||||
- NOTE: Authconfig is deprecated, this is present temporarily
|
||||
- as long as we want to provide backward compatibility
|
||||
- for the authconfig command in kickstart.
|
||||
- """
|
||||
-
|
||||
- def __init__(self, sysroot, authconfig_options):
|
||||
- """Create a new Authconfig configuration task.
|
||||
-
|
||||
- :param str sysroot: a path to the root of the target system
|
||||
- :param list authconfig_options: options for authconfig
|
||||
- """
|
||||
- super().__init__()
|
||||
- self._sysroot = sysroot
|
||||
- self._authconfig_options = authconfig_options
|
||||
-
|
||||
- @property
|
||||
- def name(self):
|
||||
- return "Authconfig configuration"
|
||||
-
|
||||
- def run(self):
|
||||
- # Apply the authconfig options from the kickstart file (deprecated).
|
||||
- if self._authconfig_options:
|
||||
- run_auth_tool(
|
||||
- AUTHCONFIG_TOOL_PATH,
|
||||
- ["--update", "--nostart"] + self._authconfig_options,
|
||||
- self._sysroot
|
||||
- )
|
||||
diff --git a/pyanaconda/modules/security/kickstart.py b/pyanaconda/modules/security/kickstart.py
|
||||
index 1adbc72934..24cbb03253 100644
|
||||
--- a/pyanaconda/modules/security/kickstart.py
|
||||
+++ b/pyanaconda/modules/security/kickstart.py
|
||||
@@ -23,8 +23,6 @@
|
||||
class SecurityKickstartSpecification(KickstartSpecification):
|
||||
|
||||
commands = {
|
||||
- "auth": COMMANDS.Authconfig,
|
||||
- "authconfig": COMMANDS.Authconfig,
|
||||
"authselect": COMMANDS.Authselect,
|
||||
"selinux": COMMANDS.SELinux,
|
||||
"realm": COMMANDS.Realm
|
||||
diff --git a/pyanaconda/modules/security/security.py b/pyanaconda/modules/security/security.py
|
||||
index b4e9f3f..de1b7f1 100644
|
||||
--- a/pyanaconda/modules/security/security.py
|
||||
+++ b/pyanaconda/modules/security/security.py
|
||||
@@ -32,7 +32,7 @@ from pyanaconda.modules.security.kickstart import SecurityKickstartSpecification
|
||||
from pyanaconda.modules.security.security_interface import SecurityInterface
|
||||
from pyanaconda.modules.security.installation import ConfigureSELinuxTask, \
|
||||
RealmDiscoverTask, RealmJoinTask, ConfigureAuthselectTask, \
|
||||
- ConfigureAuthconfigTask, ConfigureFingerprintAuthTask
|
||||
+ ConfigureFingerprintAuthTask
|
||||
|
||||
from pyanaconda.anaconda_loggers import get_module_logger
|
||||
log = get_module_logger(__name__)
|
||||
@@ -50,9 +50,6 @@ class SecurityService(KickstartService):
|
||||
self.authselect_changed = Signal()
|
||||
self._authselect_args = []
|
||||
|
||||
- self.authconfig_changed = Signal()
|
||||
- self._authconfig_args = []
|
||||
-
|
||||
self.fingerprint_auth_enabled_changed = Signal()
|
||||
self._fingerprint_auth_enabled = False
|
||||
|
||||
@@ -78,9 +75,6 @@ class SecurityService(KickstartService):
|
||||
if data.authselect.authselect:
|
||||
self.set_authselect(shlex.split(data.authselect.authselect))
|
||||
|
||||
- if data.authconfig.authconfig:
|
||||
- self.set_authconfig(shlex.split(data.authconfig.authconfig))
|
||||
-
|
||||
if data.realm.join_realm:
|
||||
realm = RealmData()
|
||||
realm.name = data.realm.join_realm
|
||||
@@ -97,9 +91,6 @@ class SecurityService(KickstartService):
|
||||
if self.authselect:
|
||||
data.authselect.authselect = " ".join(self.authselect)
|
||||
|
||||
- if self.authconfig:
|
||||
- data.authconfig.authconfig = " ".join(self.authconfig)
|
||||
-
|
||||
if self.realm.name:
|
||||
data.realm.join_realm = self.realm.name
|
||||
data.realm.discover_options = self.realm.discover_options
|
||||
@@ -139,27 +130,6 @@ class SecurityService(KickstartService):
|
||||
self.authselect_changed.emit()
|
||||
log.debug("Authselect is set to %s.", args)
|
||||
|
||||
- @property
|
||||
- def authconfig(self):
|
||||
- """Arguments for the authconfig tool.
|
||||
-
|
||||
- Authconfig is deprecated, use authselect.
|
||||
-
|
||||
- :return: a list of arguments
|
||||
- """
|
||||
- return self._authconfig_args
|
||||
-
|
||||
- def set_authconfig(self, args):
|
||||
- """Set the arguments for the authconfig tool.
|
||||
-
|
||||
- Authconfig is deprecated, use authselect.
|
||||
-
|
||||
- :param args: a list of arguments
|
||||
- """
|
||||
- self._authconfig_args = args
|
||||
- self.authconfig_changed.emit()
|
||||
- log.debug("Authconfig is set to %s.", args)
|
||||
-
|
||||
@property
|
||||
def fingerprint_auth_enabled(self):
|
||||
"""Specifies if fingerprint authentication should be enabled.
|
||||
@@ -216,7 +186,7 @@ class SecurityService(KickstartService):
|
||||
for name in self.realm.required_packages:
|
||||
requirements.append(Requirement.for_package(name, reason="Needed to join a realm."))
|
||||
|
||||
- # Add authselect / authconfig requirements
|
||||
+ # Add authselect requirements
|
||||
if self.authselect or self.fingerprint_auth_enabled:
|
||||
# we need the authselect package in two cases:
|
||||
# - autselect command is used in kickstart
|
||||
@@ -227,12 +197,6 @@ class SecurityService(KickstartService):
|
||||
"for fingerprint authentication support."
|
||||
))
|
||||
|
||||
- if self.authconfig:
|
||||
- requirements.append(Requirement.for_package(
|
||||
- "authselect-compat",
|
||||
- reason="Needed to support legacy authconfig kickstart command."
|
||||
- ))
|
||||
-
|
||||
return requirements
|
||||
|
||||
def discover_realm_with_task(self):
|
||||
@@ -271,9 +235,5 @@ class SecurityService(KickstartService):
|
||||
ConfigureAuthselectTask(
|
||||
sysroot=conf.target.system_root,
|
||||
authselect_options=self.authselect
|
||||
- ),
|
||||
- ConfigureAuthconfigTask(
|
||||
- sysroot=conf.target.system_root,
|
||||
- authconfig_options=self.authconfig
|
||||
)
|
||||
]
|
||||
diff --git a/pyanaconda/modules/security/security_interface.py b/pyanaconda/modules/security/security_interface.py
|
||||
index 5191b39..537b972 100644
|
||||
--- a/pyanaconda/modules/security/security_interface.py
|
||||
+++ b/pyanaconda/modules/security/security_interface.py
|
||||
@@ -35,7 +35,6 @@ class SecurityInterface(KickstartModuleInterface):
|
||||
super().connect_signals()
|
||||
self.watch_property("SELinux", self.implementation.selinux_changed)
|
||||
self.watch_property("Authselect", self.implementation.authselect_changed)
|
||||
- self.watch_property("Authconfig", self.implementation.authconfig_changed)
|
||||
self.watch_property(
|
||||
"FingerprintAuthEnabled", self.implementation.fingerprint_auth_enabled_changed
|
||||
)
|
||||
@@ -83,28 +82,6 @@ class SecurityInterface(KickstartModuleInterface):
|
||||
"""
|
||||
self.implementation.set_authselect(args)
|
||||
|
||||
- @property
|
||||
- def Authconfig(self) -> List[Str]:
|
||||
- """Arguments for the authconfig tool.
|
||||
-
|
||||
- Authconfig is deprecated, use authselect.
|
||||
-
|
||||
- :return: a list of arguments
|
||||
- """
|
||||
- return self.implementation.authconfig
|
||||
-
|
||||
- @emits_properties_changed
|
||||
- def SetAuthconfig(self, args: List[Str]):
|
||||
- """Set the arguments for the authconfig tool.
|
||||
-
|
||||
- Authconfig is deprecated, use authselect.
|
||||
-
|
||||
- Example: ['--passalgo=sha512', '--useshadow']
|
||||
-
|
||||
- :param args: a list of arguments
|
||||
- """
|
||||
- self.implementation.set_authconfig(args)
|
||||
-
|
||||
@property
|
||||
def Realm(self) -> Structure:
|
||||
"""Specification of the enrollment in a realm.
|
||||
diff --git a/tests/nosetests/pyanaconda_tests/module_security_test.py b/tests/nosetests/pyanaconda_tests/module_security_test.py
|
||||
index 9ea41ec..9fe23e9 100644
|
||||
--- a/tests/nosetests/pyanaconda_tests/module_security_test.py
|
||||
+++ b/tests/nosetests/pyanaconda_tests/module_security_test.py
|
||||
@@ -33,8 +33,8 @@ from pyanaconda.modules.security.security_interface import SecurityInterface
|
||||
from pyanaconda.modules.security.constants import SELinuxMode
|
||||
from pyanaconda.modules.security.installation import ConfigureSELinuxTask, \
|
||||
RealmDiscoverTask, RealmJoinTask, ConfigureFingerprintAuthTask, \
|
||||
- ConfigureAuthselectTask, ConfigureAuthconfigTask, AUTHSELECT_TOOL_PATH, \
|
||||
- AUTHCONFIG_TOOL_PATH, PAM_SO_64_PATH, PAM_SO_PATH
|
||||
+ ConfigureAuthselectTask, AUTHSELECT_TOOL_PATH, \
|
||||
+ PAM_SO_64_PATH, PAM_SO_PATH
|
||||
from tests.nosetests.pyanaconda_tests import patch_dbus_publish_object, check_kickstart_interface, \
|
||||
check_task_creation, check_task_creation_list, PropertiesChangedCallback, check_dbus_property
|
||||
from pyanaconda.modules.common.structures.requirement import Requirement
|
||||
@@ -64,7 +64,7 @@ class SecurityInterfaceTestCase(unittest.TestCase):
|
||||
def kickstart_properties_test(self):
|
||||
"""Test kickstart properties."""
|
||||
self.assertEqual(self.security_interface.KickstartCommands,
|
||||
- ["auth", "authconfig", "authselect", "selinux", "realm"])
|
||||
+ ["authselect", "selinux", "realm"])
|
||||
self.assertEqual(self.security_interface.KickstartSections, [])
|
||||
self.assertEqual(self.security_interface.KickstartAddons, [])
|
||||
self.callback.assert_not_called()
|
||||
@@ -83,13 +83,6 @@ class SecurityInterfaceTestCase(unittest.TestCase):
|
||||
["sssd", "with-mkhomedir"]
|
||||
)
|
||||
|
||||
- def authconfig_property_test(self):
|
||||
- """Test the authconfig property."""
|
||||
- self._check_dbus_property(
|
||||
- "Authconfig",
|
||||
- ["--passalgo=sha512", "--useshadow"]
|
||||
- )
|
||||
-
|
||||
def fingerprint_auth_enabled_test(self):
|
||||
"""Test the fingerprint_auth_enabled property."""
|
||||
self._check_dbus_property(
|
||||
@@ -137,28 +130,6 @@ class SecurityInterfaceTestCase(unittest.TestCase):
|
||||
"""
|
||||
self._test_kickstart(ks_in, ks_out)
|
||||
|
||||
- def auth_kickstart_test(self):
|
||||
- """Test the auth command."""
|
||||
- ks_in = """
|
||||
- auth --passalgo=sha512 --useshadow
|
||||
- """
|
||||
- ks_out = """
|
||||
- # System authorization information
|
||||
- auth --passalgo=sha512 --useshadow
|
||||
- """
|
||||
- self._test_kickstart(ks_in, ks_out)
|
||||
-
|
||||
- def authconfig_kickstart_test(self):
|
||||
- """Test the authconfig command."""
|
||||
- ks_in = """
|
||||
- authconfig --passalgo=sha512 --useshadow
|
||||
- """
|
||||
- ks_out = """
|
||||
- # System authorization information
|
||||
- auth --passalgo=sha512 --useshadow
|
||||
- """
|
||||
- self._test_kickstart(ks_in, ks_out)
|
||||
-
|
||||
def authselect_kickstart_test(self):
|
||||
"""Test the authselect command."""
|
||||
ks_in = """
|
||||
@@ -210,7 +181,6 @@ class SecurityInterfaceTestCase(unittest.TestCase):
|
||||
ConfigureSELinuxTask,
|
||||
ConfigureFingerprintAuthTask,
|
||||
ConfigureAuthselectTask,
|
||||
- ConfigureAuthconfigTask,
|
||||
]
|
||||
task_paths = self.security_interface.InstallWithTasks()
|
||||
task_objs = check_task_creation_list(self, task_paths, publisher, task_classes)
|
||||
@@ -224,9 +194,6 @@ class SecurityInterfaceTestCase(unittest.TestCase):
|
||||
# ConfigureAuthselectTask
|
||||
obj = task_objs[2]
|
||||
self.assertEqual(obj.implementation._authselect_options, [])
|
||||
- # ConfigureAuthconfigTask
|
||||
- obj = task_objs[3]
|
||||
- self.assertEqual(obj.implementation._authconfig_options, [])
|
||||
|
||||
@patch_dbus_publish_object
|
||||
def realm_join_default_test(self, publisher):
|
||||
@@ -247,20 +214,17 @@ class SecurityInterfaceTestCase(unittest.TestCase):
|
||||
realm.discovered = True
|
||||
|
||||
authselect = ['select', 'sssd']
|
||||
- authconfig = ['--passalgo=sha512', '--useshadow']
|
||||
fingerprint = True
|
||||
|
||||
self.security_interface.SetRealm(RealmData.to_structure(realm))
|
||||
self.security_interface.SetSELinux(SELINUX_PERMISSIVE)
|
||||
self.security_interface.SetAuthselect(authselect)
|
||||
- self.security_interface.SetAuthconfig(authconfig)
|
||||
self.security_interface.SetFingerprintAuthEnabled(fingerprint)
|
||||
|
||||
task_classes = [
|
||||
ConfigureSELinuxTask,
|
||||
ConfigureFingerprintAuthTask,
|
||||
ConfigureAuthselectTask,
|
||||
- ConfigureAuthconfigTask,
|
||||
]
|
||||
task_paths = self.security_interface.InstallWithTasks()
|
||||
task_objs = check_task_creation_list(self, task_paths, publisher, task_classes)
|
||||
@@ -274,9 +238,6 @@ class SecurityInterfaceTestCase(unittest.TestCase):
|
||||
# ConfigureAuthselectTask
|
||||
obj = task_objs[2]
|
||||
self.assertEqual(obj.implementation._authselect_options, authselect)
|
||||
- # ConfigureAuthconfigTask
|
||||
- obj = task_objs[3]
|
||||
- self.assertEqual(obj.implementation._authconfig_options, authconfig)
|
||||
|
||||
@patch_dbus_publish_object
|
||||
def realm_join_configured_test(self, publisher):
|
||||
@@ -366,15 +327,6 @@ class SecurityInterfaceTestCase(unittest.TestCase):
|
||||
def authselect_requirements_test(self):
|
||||
"""Test that package requirements for authselect propagate correctly."""
|
||||
|
||||
- self.security_interface.SetAuthconfig(['--passalgo=sha512', '--useshadow'])
|
||||
- requirements = Requirement.from_structure_list(
|
||||
- self.security_interface.CollectRequirements()
|
||||
- )
|
||||
- self.assertEqual(len(requirements), 1)
|
||||
- self.assertEqual(requirements[0].type, "package")
|
||||
- self.assertEqual(requirements[0].name, "authselect-compat")
|
||||
-
|
||||
- self.security_interface.SetAuthconfig([])
|
||||
self.security_interface.SetAuthselect(['select', 'sssd'])
|
||||
requirements = Requirement.from_structure_list(
|
||||
self.security_interface.CollectRequirements()
|
||||
@@ -383,7 +335,6 @@ class SecurityInterfaceTestCase(unittest.TestCase):
|
||||
self.assertEqual(requirements[0].type, "package")
|
||||
self.assertEqual(requirements[0].name, "authselect")
|
||||
|
||||
- self.security_interface.SetAuthconfig([])
|
||||
self.security_interface.SetAuthselect([])
|
||||
self.security_interface.SetFingerprintAuthEnabled(True)
|
||||
requirements = Requirement.from_structure_list(
|
||||
@@ -860,37 +811,3 @@ class SecurityTasksTestCase(unittest.TestCase):
|
||||
root=sysroot
|
||||
)
|
||||
os.remove(authselect_path)
|
||||
-
|
||||
- @patch('pyanaconda.core.util.execWithRedirect')
|
||||
- def configure_authconfig_task_test(self, execWithRedirect):
|
||||
- """Test the configure authconfig task."""
|
||||
- with tempfile.TemporaryDirectory() as sysroot:
|
||||
-
|
||||
- authconfig_dir = os.path.normpath(sysroot + os.path.dirname(AUTHCONFIG_TOOL_PATH))
|
||||
- authconfig_path = os.path.normpath(sysroot + AUTHCONFIG_TOOL_PATH)
|
||||
- os.makedirs(authconfig_dir)
|
||||
-
|
||||
- # The authconfig command is missing
|
||||
- execWithRedirect.reset_mock()
|
||||
- task = ConfigureAuthconfigTask(
|
||||
- sysroot=sysroot,
|
||||
- authconfig_options=["--passalgo=sha512", "--useshadow"]
|
||||
- )
|
||||
- with self.assertRaises(SecurityInstallationError):
|
||||
- task.run()
|
||||
- execWithRedirect.assert_not_called()
|
||||
-
|
||||
- # The authconfig command is there
|
||||
- execWithRedirect.reset_mock()
|
||||
- os.mknod(authconfig_path)
|
||||
- task = ConfigureAuthconfigTask(
|
||||
- sysroot=sysroot,
|
||||
- authconfig_options=["--passalgo=sha512", "--useshadow"]
|
||||
- )
|
||||
- task.run()
|
||||
- execWithRedirect.assert_called_once_with(
|
||||
- AUTHCONFIG_TOOL_PATH,
|
||||
- ["--update", "--nostart", "--passalgo=sha512", "--useshadow"],
|
||||
- root=sysroot
|
||||
- )
|
||||
- os.remove(authconfig_path)
|
||||
--
|
||||
2.27.0
|
||||
@ -1,47 +0,0 @@
|
||||
From 018ab707bd2af446f6e6bd1c8e9384178333c0b9 Mon Sep 17 00:00:00 2001
|
||||
From: Javier Martinez Canillas <javierm@redhat.com>
|
||||
Date: Thu, 4 Aug 2022 19:33:40 +0800
|
||||
Subject: [PATCH] revert "Set default entry to the BLS id instead of the entry index"
|
||||
|
||||
revert the patch of "Set default entry to the BLS id instead of the entry index"
|
||||
Reference:https://github.com/rhinstaller/anaconda/commit/a252e4424bd51d6236d3b7b8e3840d8ca0af90a2
|
||||
Conflict:https://github.com/rhinstaller/anaconda/commit/a252e4424bd51d6236d3b7b8e3840d8ca0af90a2
|
||||
|
||||
---
|
||||
.../modules/storage/bootloader/grub2.py | 20 +++++++++----------
|
||||
1 file changed, 10 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/bootloader/grub2.py b/pyanaconda/modules/storage/bootloader/grub2.py
|
||||
index 3209ab7..6a6441b 100644
|
||||
--- a/pyanaconda/modules/storage/bootloader/grub2.py
|
||||
+++ b/pyanaconda/modules/storage/bootloader/grub2.py
|
||||
@@ -335,16 +335,16 @@ class GRUB2(BootLoader):
|
||||
|
||||
# make sure the default entry is the OS we are installing
|
||||
if self.default is not None:
|
||||
- machine_id_path = conf.target.system_root + "/etc/machine-id"
|
||||
- if not os.access(machine_id_path, os.R_OK):
|
||||
- log.error("failed to read machine-id, default entry not set")
|
||||
- return
|
||||
-
|
||||
- with open(machine_id_path, "r") as fd:
|
||||
- machine_id = fd.readline().strip()
|
||||
-
|
||||
- default_entry = "%s-%s" % (machine_id, self.default.version)
|
||||
- rc = util.execInSysroot("grub2-set-default", [default_entry])
|
||||
+ # find the index of the default image
|
||||
+ try:
|
||||
+ default_index = self.images.index(self.default)
|
||||
+ except ValueError:
|
||||
+ # pylint: disable=no-member
|
||||
+ log.warning("Failed to find default image (%s), defaulting to 0",
|
||||
+ self.default.label)
|
||||
+ default_index = 0
|
||||
+
|
||||
+ rc = util.execInSysroot("grub2-set-default", [str(default_index)])
|
||||
if rc:
|
||||
log.error("failed to set default menu entry to %s", productName)
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
From f7398e8ceaa634bff73b1b1cd04ac0aa572d5249 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Pitt <martin@piware.de>
|
||||
Date: Thu, 1 Oct 2020 15:44:43 +0200
|
||||
Subject: [PATCH] Add missing "make" BuildRequires
|
||||
|
||||
The .spec calls make, and it's not present in the Fedora container
|
||||
images.
|
||||
---
|
||||
anaconda.spec.in | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/anaconda.spec.in b/anaconda.spec.in
|
||||
index d2b34a65f..5c5146c9c 100644
|
||||
--- a/anaconda.spec.in
|
||||
+++ b/anaconda.spec.in
|
||||
@@ -54,6 +54,7 @@ BuildRequires: gobject-introspection-devel
|
||||
BuildRequires: glade-devel
|
||||
BuildRequires: libgnomekbd-devel
|
||||
BuildRequires: libxklavier-devel >= %{libxklavierver}
|
||||
+BuildRequires: make
|
||||
BuildRequires: pango-devel
|
||||
BuildRequires: python3-kickstart >= %{pykickstartver}
|
||||
BuildRequires: python3-devel
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
From 8437fe761224a97967a076e05143304a225c3e05 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Mosnacek <omosnace@redhat.com>
|
||||
Date: Fri, 2 Oct 2020 13:06:26 +0200
|
||||
Subject: [PATCH] Add selinux=0 boot parameter when SELinux is set to disabled
|
||||
(#1882464)
|
||||
|
||||
We are trying to eliminate the reliance on disabling SELinux via
|
||||
/etc/selinux/config in Fedora [1], since this functionality is being
|
||||
deprecated upstream.
|
||||
|
||||
Even though only setting SELINUX=disabled in /etc/selinux/config will
|
||||
still lead to a similar result as if SELinux would be disabled
|
||||
completely, users might complain that Anaconda didn't actually do the
|
||||
right thing, so let's make sure it is done properly by adding selinux=0
|
||||
to the target system's kernel command line when the user requests
|
||||
SELinux to be disabled via anaconda command line or kickstart.
|
||||
|
||||
[1] https://fedoraproject.org/wiki/Changes/Remove_Support_For_SELinux_Runtime_Disable
|
||||
|
||||
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
|
||||
---
|
||||
pyanaconda/modules/storage/bootloader/base.py | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/bootloader/base.py b/pyanaconda/modules/storage/bootloader/base.py
|
||||
index d690ca056..12f8f54b2 100644
|
||||
--- a/pyanaconda/modules/storage/bootloader/base.py
|
||||
+++ b/pyanaconda/modules/storage/bootloader/base.py
|
||||
@@ -35,8 +35,9 @@ from pyanaconda.core.configuration.anaconda import conf
|
||||
from pyanaconda.core.i18n import N_, _
|
||||
from pyanaconda.modules.common.constants.objects import FCOE, ISCSI, BOOTLOADER
|
||||
from pyanaconda.modules.common.structures.iscsi import Node
|
||||
-from pyanaconda.modules.common.constants.services import STORAGE, NETWORK
|
||||
+from pyanaconda.modules.common.constants.services import STORAGE, NETWORK, SECURITY
|
||||
from pyanaconda.modules.common.structures.network import NetworkDeviceInfo
|
||||
+from pykickstart.constants import SELINUX_DISABLED
|
||||
|
||||
log = get_module_logger(__name__)
|
||||
|
||||
@@ -729,6 +730,7 @@ class BootLoader(object):
|
||||
self._set_storage_boot_args(storage)
|
||||
self._preserve_some_boot_args()
|
||||
self._set_graphical_boot_args()
|
||||
+ self._set_security_boot_args()
|
||||
|
||||
def _set_extra_boot_args(self):
|
||||
"""Set the extra boot args."""
|
||||
@@ -885,6 +887,12 @@ class BootLoader(object):
|
||||
self.boot_args.update(args)
|
||||
self.dracut_args.update(args)
|
||||
|
||||
+ def _set_security_boot_args(self):
|
||||
+ """Set LSM-related boot args."""
|
||||
+ proxy = SECURITY.get_proxy()
|
||||
+ if proxy.SELinux == SELINUX_DISABLED:
|
||||
+ self.boot_args.add('selinux=0')
|
||||
+
|
||||
#
|
||||
# configuration
|
||||
#
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,149 +0,0 @@
|
||||
From cf8d3811b89b90211cac0cbd1e5ceb40ea7b641b Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Mon, 7 Sep 2020 17:09:15 +0200
|
||||
Subject: [PATCH] Add the DBus method IsDeviceShrinkable (#1875677)
|
||||
|
||||
Replace the DBus method IsDeviceResizable with IsDeviceShrinkable and fix its
|
||||
implementation. A shrinkable device has to be resizable and its minimal size
|
||||
has to be lower then the current size. This should fix the issue with XFS, that
|
||||
is resizable, but not shrinkable.
|
||||
|
||||
Resolves: rhbz#1875677
|
||||
---
|
||||
.../automatic/resizable_interface.py | 6 ++--
|
||||
.../automatic/resizable_module.py | 6 ++--
|
||||
pyanaconda/ui/gui/spokes/lib/resize.py | 10 +++----
|
||||
.../pyanaconda_tests/module_resizable_test.py | 29 +++++++++++++++----
|
||||
4 files changed, 34 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/partitioning/automatic/resizable_interface.py b/pyanaconda/modules/storage/partitioning/automatic/resizable_interface.py
|
||||
index 760a49ecb..c531a0b42 100644
|
||||
--- a/pyanaconda/modules/storage/partitioning/automatic/resizable_interface.py
|
||||
+++ b/pyanaconda/modules/storage/partitioning/automatic/resizable_interface.py
|
||||
@@ -37,13 +37,13 @@ class ResizableDeviceTreeInterface(DeviceTreeInterface):
|
||||
"""
|
||||
return self.implementation.is_device_partitioned(device_name)
|
||||
|
||||
- def IsDeviceResizable(self, device_name: Str) -> Bool:
|
||||
- """Is the specified device resizable?
|
||||
+ def IsDeviceShrinkable(self, device_name: Str) -> Bool:
|
||||
+ """Is the specified device shrinkable?
|
||||
|
||||
:param device_name: a name of the device
|
||||
:return: True or False
|
||||
"""
|
||||
- return self.implementation.is_device_resizable(device_name)
|
||||
+ return self.implementation.is_device_shrinkable(device_name)
|
||||
|
||||
def GetDevicePartitions(self, device_name: Str) -> List[Str]:
|
||||
"""Get partitions of the specified device.
|
||||
diff --git a/pyanaconda/modules/storage/partitioning/automatic/resizable_module.py b/pyanaconda/modules/storage/partitioning/automatic/resizable_module.py
|
||||
index 9603dfc1b..12d32e891 100644
|
||||
--- a/pyanaconda/modules/storage/partitioning/automatic/resizable_module.py
|
||||
+++ b/pyanaconda/modules/storage/partitioning/automatic/resizable_module.py
|
||||
@@ -52,14 +52,14 @@ class ResizableDeviceTreeModule(DeviceTreeModule):
|
||||
"""Is the specified device partitioned?"""
|
||||
return device.is_disk and device.partitioned and device.format.supported
|
||||
|
||||
- def is_device_resizable(self, device_name):
|
||||
- """Is the specified device resizable?
|
||||
+ def is_device_shrinkable(self, device_name):
|
||||
+ """Is the specified device shrinkable?
|
||||
|
||||
:param device_name: a name of the device
|
||||
:return: True or False
|
||||
"""
|
||||
device = self._get_device(device_name)
|
||||
- return device.resizable
|
||||
+ return device.resizable and device.min_size < device.size
|
||||
|
||||
def get_device_partitions(self, device_name):
|
||||
"""Get partitions of the specified device.
|
||||
diff --git a/pyanaconda/ui/gui/spokes/lib/resize.py b/pyanaconda/ui/gui/spokes/lib/resize.py
|
||||
index 4695e5332..ee165ada7 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/lib/resize.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/lib/resize.py
|
||||
@@ -228,13 +228,13 @@ class ResizeDialog(GUIObject):
|
||||
|
||||
# Calculate the free size.
|
||||
# Devices that are not resizable are still deletable.
|
||||
- is_resizable = self._device_tree.IsDeviceResizable(device_name)
|
||||
+ is_shrinkable = self._device_tree.IsDeviceShrinkable(device_name)
|
||||
size_limits = self._device_tree.GetDeviceSizeLimits(device_name)
|
||||
|
||||
min_size = Size(size_limits[0])
|
||||
device_size = Size(device_data.size)
|
||||
|
||||
- if is_resizable:
|
||||
+ if is_shrinkable:
|
||||
free_size = device_size - min_size
|
||||
resize_string = _("%(freeSize)s of %(devSize)s") % {
|
||||
"freeSize": free_size.human_readable(max_places=1),
|
||||
@@ -394,10 +394,10 @@ class ResizeDialog(GUIObject):
|
||||
|
||||
# If the selected filesystem does not support shrinking, make that
|
||||
# button insensitive.
|
||||
- is_resizable = self._device_tree.IsDeviceResizable(device_name)
|
||||
- self._shrink_button.set_sensitive(is_resizable)
|
||||
+ is_shrinkable = self._device_tree.IsDeviceShrinkable(device_name)
|
||||
+ self._shrink_button.set_sensitive(is_shrinkable)
|
||||
|
||||
- if is_resizable:
|
||||
+ if is_shrinkable:
|
||||
min_size = self._device_tree.GetDeviceSizeLimits(device_name)[0]
|
||||
self._setup_slider(min_size, device_data.size, Size(obj.target))
|
||||
|
||||
diff --git a/tests/nosetests/pyanaconda_tests/module_resizable_test.py b/tests/nosetests/pyanaconda_tests/module_resizable_test.py
|
||||
index 3c60e166b..42880b4ca 100644
|
||||
--- a/tests/nosetests/pyanaconda_tests/module_resizable_test.py
|
||||
+++ b/tests/nosetests/pyanaconda_tests/module_resizable_test.py
|
||||
@@ -18,9 +18,11 @@
|
||||
# Red Hat Author(s): Vendula Poncova <vponcova@redhat.com>
|
||||
#
|
||||
import unittest
|
||||
+from unittest.mock import patch
|
||||
|
||||
from blivet.devices import StorageDevice, DiskDevice, PartitionDevice
|
||||
from blivet.formats import get_format
|
||||
+from blivet.formats.fs import FS
|
||||
from blivet.size import Size
|
||||
|
||||
from pyanaconda.modules.storage.partitioning.automatic.resizable_interface import \
|
||||
@@ -66,13 +68,28 @@ class ResizableDeviceTreeTestCase(unittest.TestCase):
|
||||
self.assertEqual(self.interface.IsDevicePartitioned("dev1"), False)
|
||||
self.assertEqual(self.interface.IsDevicePartitioned("dev2"), True)
|
||||
|
||||
- def is_device_resizable_test(self):
|
||||
- """Test IsDeviceResizable."""
|
||||
+ @patch.object(FS, "update_size_info")
|
||||
+ def is_device_shrinkable_test(self, update_size_info):
|
||||
+ """Test IsDeviceShrinkable."""
|
||||
self.module.on_storage_changed(create_storage())
|
||||
- self._add_device(StorageDevice(
|
||||
- "dev1"
|
||||
- ))
|
||||
- self.assertEqual(self.interface.IsDeviceResizable("dev1"), False)
|
||||
+
|
||||
+ dev1 = StorageDevice(
|
||||
+ "dev1",
|
||||
+ exists=True,
|
||||
+ size=Size("10 GiB"),
|
||||
+ fmt=get_format(None, exists=True)
|
||||
+ )
|
||||
+
|
||||
+ self._add_device(dev1)
|
||||
+ self.assertEqual(self.interface.IsDeviceShrinkable("dev1"), False)
|
||||
+
|
||||
+ dev1._resizable = True
|
||||
+ dev1.format._resizable = True
|
||||
+ dev1.format._min_size = Size("1 GiB")
|
||||
+ self.assertEqual(self.interface.IsDeviceShrinkable("dev1"), True)
|
||||
+
|
||||
+ dev1.format._min_size = Size("10 GiB")
|
||||
+ self.assertEqual(self.interface.IsDeviceShrinkable("dev1"), False)
|
||||
|
||||
def get_device_partitions_test(self):
|
||||
"""Test GetDevicePartitions."""
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
From d1d43dc872aa05b7273883fe42debd55e11e6df6 Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Mon, 5 Oct 2020 18:57:24 +0200
|
||||
Subject: [PATCH] Allow to format selected DASDs
|
||||
|
||||
TUI should allow to format selected DASDs the same way as GUI.
|
||||
|
||||
(cherry-picked from a commit 4f1bc77)
|
||||
|
||||
Related: rhbz#1874394
|
||||
---
|
||||
pyanaconda/ui/tui/spokes/storage.py | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/pyanaconda/ui/tui/spokes/storage.py b/pyanaconda/ui/tui/spokes/storage.py
|
||||
index 813dbb052..4ed97d27e 100644
|
||||
--- a/pyanaconda/ui/tui/spokes/storage.py
|
||||
+++ b/pyanaconda/ui/tui/spokes/storage.py
|
||||
@@ -258,6 +258,10 @@ class StorageSpoke(NormalTUISpoke):
|
||||
# Wait for storage.
|
||||
threadMgr.wait(THREAD_STORAGE)
|
||||
|
||||
+ # Allow to format DASDs.
|
||||
+ self._disk_init_module.SetFormatUnrecognizedEnabled(True)
|
||||
+ self._disk_init_module.SetFormatLDLEnabled(True)
|
||||
+
|
||||
# Get selected disks.
|
||||
disks = filter_disks_by_names(self._available_disks, self._selected_disks)
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
From 9ef262fbd07508a5dd9becb30a0136fded45e792 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Thu, 3 Sep 2020 14:53:18 +0200
|
||||
Subject: [PATCH] Always clear treeinfo metadata (#1872056)
|
||||
|
||||
Metadata from the treeinfo were loaded only during the load of new metadata.
|
||||
However, this does not work if we have source without metadata (e.g.
|
||||
mirrorlist). In that case we are loading additional repositories from the old
|
||||
metadata (not mounted anymore) and not the new ones which may have unexpected
|
||||
results.
|
||||
|
||||
Resolves: rhbz#1872056
|
||||
---
|
||||
pyanaconda/payload/dnf/payload.py | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/pyanaconda/payload/dnf/payload.py b/pyanaconda/payload/dnf/payload.py
|
||||
index 5fba7e0e7..880886685 100644
|
||||
--- a/pyanaconda/payload/dnf/payload.py
|
||||
+++ b/pyanaconda/payload/dnf/payload.py
|
||||
@@ -1477,6 +1477,7 @@ class DNFPayload(Payload):
|
||||
def reset(self):
|
||||
tear_down_sources(self.proxy)
|
||||
self.reset_additional_repos()
|
||||
+ self._install_tree_metadata = None
|
||||
|
||||
shutil.rmtree(DNF_CACHE_DIR, ignore_errors=True)
|
||||
shutil.rmtree(DNF_PLUGINCONF_DIR, ignore_errors=True)
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
From 6326cb3e866027a5862c0fbd0a1f0a2a86b6836b Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Tue, 23 Jun 2020 17:55:37 +0200
|
||||
Subject: [PATCH] Always specify the boot disk
|
||||
|
||||
We should always specify the boot disk when we allocate partitions. Otherwise,
|
||||
Blivet will choose one of the available disks that don't have to be valid.
|
||||
|
||||
(cherry-picked from a commit 856e011)
|
||||
---
|
||||
.../storage/partitioning/automatic/automatic_partitioning.py | 2 +-
|
||||
.../modules/storage/partitioning/custom/custom_partitioning.py | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/partitioning/automatic/automatic_partitioning.py b/pyanaconda/modules/storage/partitioning/automatic/automatic_partitioning.py
|
||||
index acceb4b4e..a88c55d4d 100644
|
||||
--- a/pyanaconda/modules/storage/partitioning/automatic/automatic_partitioning.py
|
||||
+++ b/pyanaconda/modules/storage/partitioning/automatic/automatic_partitioning.py
|
||||
@@ -175,7 +175,7 @@ class AutomaticPartitioningTask(NonInteractivePartitioningTask):
|
||||
devs = schedule_partitions(storage, disks, devs, scheme, requests, encrypted, luks_fmt_args)
|
||||
|
||||
# run the autopart function to allocate and grow partitions
|
||||
- do_partitioning(storage)
|
||||
+ do_partitioning(storage, boot_disk=storage.bootloader.stage1_disk)
|
||||
schedule_volumes(storage, devs, scheme, requests, encrypted)
|
||||
|
||||
# grow LVs
|
||||
diff --git a/pyanaconda/modules/storage/partitioning/custom/custom_partitioning.py b/pyanaconda/modules/storage/partitioning/custom/custom_partitioning.py
|
||||
index 218bbe13f..754a48e2e 100644
|
||||
--- a/pyanaconda/modules/storage/partitioning/custom/custom_partitioning.py
|
||||
+++ b/pyanaconda/modules/storage/partitioning/custom/custom_partitioning.py
|
||||
@@ -136,7 +136,7 @@ class CustomPartitioningTask(NonInteractivePartitioningTask):
|
||||
self._execute_partition_data(storage, data, partition_data)
|
||||
|
||||
if data.partition.partitions:
|
||||
- do_partitioning(storage)
|
||||
+ do_partitioning(storage, boot_disk=storage.bootloader.stage1_disk)
|
||||
|
||||
def _execute_partition_data(self, storage, data, partition_data):
|
||||
"""Execute the partition data.
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
From b7258aafb1e55b055bc6bcd18b10c83f5a5feec6 Mon Sep 17 00:00:00 2001
|
||||
From: Radek Vykydal <rvykydal@redhat.com>
|
||||
Date: Wed, 29 Jul 2020 12:43:26 +0200
|
||||
Subject: [PATCH] Apply onboot policy even when network was configured in UI.
|
||||
|
||||
Resolves: rhbz#1856632
|
||||
---
|
||||
pyanaconda/modules/network/network.py | 3 ---
|
||||
1 file changed, 3 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/network/network.py b/pyanaconda/modules/network/network.py
|
||||
index aa5a14b38..507d3b5c1 100644
|
||||
--- a/pyanaconda/modules/network/network.py
|
||||
+++ b/pyanaconda/modules/network/network.py
|
||||
@@ -372,9 +372,6 @@ class NetworkService(KickstartService):
|
||||
# Not if any network device was configured via kickstart.
|
||||
if self._original_network_data:
|
||||
return False
|
||||
- # Not if any network device was configured in UI.
|
||||
- if self._use_device_configurations:
|
||||
- return False
|
||||
# Not if there is no configuration to apply the policy to
|
||||
if not self._device_configurations or not self._device_configurations.get_all():
|
||||
return False
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
From 6c8bfa8649e71d4f20eea69b57dc47b514dd498c Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Slavik <vslavik@redhat.com>
|
||||
Date: Tue, 11 Aug 2020 17:34:49 +0200
|
||||
Subject: [PATCH] Automatically break lines in labels in software selection
|
||||
spoke
|
||||
|
||||
Resolves: rhbz#1822787
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/software_selection.glade | 10 +++++++---
|
||||
1 file changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/software_selection.glade b/pyanaconda/ui/gui/spokes/software_selection.glade
|
||||
index 2965e66df..87804c72e 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/software_selection.glade
|
||||
+++ b/pyanaconda/ui/gui/spokes/software_selection.glade
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
-<!-- Generated with glade 3.18.1 -->
|
||||
+<!-- Generated with glade 3.22.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.10"/>
|
||||
<requires lib="AnacondaWidgets" version="1.0"/>
|
||||
@@ -60,10 +60,12 @@
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
+ <property name="valign">end</property>
|
||||
<property name="margin_bottom">6</property>
|
||||
<property name="hexpand">True</property>
|
||||
- <property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Base Environment</property>
|
||||
+ <property name="wrap">True</property>
|
||||
+ <property name="xalign">0</property>
|
||||
<attributes>
|
||||
<attribute name="font-desc" value="Cantarell 12"/>
|
||||
<attribute name="weight" value="normal"/>
|
||||
@@ -78,10 +80,12 @@
|
||||
<object class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
+ <property name="valign">end</property>
|
||||
<property name="margin_bottom">6</property>
|
||||
<property name="hexpand">True</property>
|
||||
- <property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Additional software for Selected Environment</property>
|
||||
+ <property name="wrap">True</property>
|
||||
+ <property name="xalign">0</property>
|
||||
<attributes>
|
||||
<attribute name="font-desc" value="Cantarell 12"/>
|
||||
<attribute name="weight" value="normal"/>
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
From ab1ec03e4b6ae7cfc492d330233b63f344f5fee8 Mon Sep 17 00:00:00 2001
|
||||
From: root <root@localhost.localdomain>
|
||||
Date: Fri, 31 Dec 2021 19:01:08 +0800
|
||||
Subject: [PATCH 1/2] init
|
||||
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/datetime_spoke.py | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/datetime_spoke.py b/pyanaconda/ui/gui/spokes/datetime_spoke.py
|
||||
index 09deabb..8ebc5bb 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/datetime_spoke.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/datetime_spoke.py
|
||||
@@ -1059,8 +1059,22 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
|
||||
def _show_no_ntp_server_warning(self):
|
||||
self.set_warning(_("You have no working NTP server configured"))
|
||||
|
||||
+ def _cancel_planned_update(self):
|
||||
+ """Cancel system time update planned by manual setting"""
|
||||
+ # cancel system time update
|
||||
+ if self._start_updating_timer:
|
||||
+ self._start_updating_timer.cancel()
|
||||
+ self._start_updating_timer = None
|
||||
+ # re-enable UI update because it will not be done by the
|
||||
+ # system time update we've just cancelled
|
||||
+ if not self._update_datetime_timer:
|
||||
+ self._update_datetime_timer = Timer()
|
||||
+ self._update_datetime_timer.timeout_sec(1, self._update_datetime)
|
||||
+
|
||||
def on_ntp_switched(self, switch, *args):
|
||||
if switch.get_active():
|
||||
+ self._cancel_planned_update()
|
||||
+
|
||||
#turned ON
|
||||
if not conf.system.can_set_time_synchronization:
|
||||
#cannot touch runtime system, not much to do here
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
From e05cc18294e67099bf87076e4f23fe5f031fecb5 Mon Sep 17 00:00:00 2001
|
||||
From: Sundeep Anand <suanand@redhat.com>
|
||||
Date: Wed, 12 Aug 2020 17:56:19 +0530
|
||||
Subject: [PATCH] Change keyboard ordering to US layout first, 'native' second.
|
||||
Resolves: rhbz#1039185
|
||||
|
||||
---
|
||||
pyanaconda/keyboard.py | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/keyboard.py b/pyanaconda/keyboard.py
|
||||
index 2c3226c6e..081fc96fd 100644
|
||||
--- a/pyanaconda/keyboard.py
|
||||
+++ b/pyanaconda/keyboard.py
|
||||
@@ -171,8 +171,10 @@ def set_x_keyboard_defaults(localization_proxy, xkl_wrapper):
|
||||
# store it normalized
|
||||
new_layouts = [normalize_layout_variant(layouts[0])]
|
||||
if not langtable.supports_ascii(layouts[0]):
|
||||
- # does not support typing ASCII chars, append the default layout
|
||||
- new_layouts.append(DEFAULT_KEYBOARD)
|
||||
+ # The default keymap setting should have "us" before the native layout
|
||||
+ # which does not support ascii,
|
||||
+ # refer: https://bugzilla.redhat.com/show_bug.cgi?id=1039185
|
||||
+ new_layouts.insert(0, DEFAULT_KEYBOARD)
|
||||
else:
|
||||
log.error("Failed to get layout for chosen locale '%s'", locale)
|
||||
new_layouts = [DEFAULT_KEYBOARD]
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,66 +0,0 @@
|
||||
From 6515d0779a41c1ea902ada86e4e911821cded92e Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Slavik <vslavik@redhat.com>
|
||||
Date: Thu, 3 Sep 2020 19:27:28 +0200
|
||||
Subject: [PATCH] Check if original partitions are mounted, too
|
||||
|
||||
Resolves: rhbz#1751698
|
||||
---
|
||||
pyanaconda/modules/storage/checker/utils.py | 30 +++++++++++++++------
|
||||
1 file changed, 22 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/checker/utils.py b/pyanaconda/modules/storage/checker/utils.py
|
||||
index ff3ee3a6b..c40aa1dc3 100644
|
||||
--- a/pyanaconda/modules/storage/checker/utils.py
|
||||
+++ b/pyanaconda/modules/storage/checker/utils.py
|
||||
@@ -417,11 +417,15 @@ def verify_luks2_memory_requirements(storage, constraints, report_error, report_
|
||||
def verify_mounted_partitions(storage, constraints, report_error, report_warning):
|
||||
""" Check the selected disks to make sure all their partitions are unmounted.
|
||||
|
||||
+ Check both the currently known and original partitions.
|
||||
+
|
||||
:param storage: a storage to check
|
||||
:param constraints: a dictionary of constraints
|
||||
:param report_error: a function for error reporting
|
||||
:param report_warning: a function for warning reporting
|
||||
"""
|
||||
+ partitions_to_check = {}
|
||||
+
|
||||
for disk in storage.disks:
|
||||
if disk.protected:
|
||||
continue
|
||||
@@ -430,14 +434,24 @@ def verify_mounted_partitions(storage, constraints, report_error, report_warning
|
||||
continue
|
||||
|
||||
for part in disk.format.partitions:
|
||||
- part_dev = storage.devicetree.get_device_by_path(part.path)
|
||||
- if part_dev and part_dev.protected:
|
||||
- log.debug("Not checking protected %s for being mounted, assuming live "
|
||||
- "image mount", part.path)
|
||||
- continue
|
||||
- if part.busy:
|
||||
- report_error(_("%s is currently mounted and cannot be used for the "
|
||||
- "installation. Please unmount it and retry.") % part.path)
|
||||
+ if part.path not in partitions_to_check:
|
||||
+ partitions_to_check[part.path] = part
|
||||
+
|
||||
+ if hasattr(disk.original_format, "partitions"):
|
||||
+ for part in disk.original_format.partitions:
|
||||
+ if part.path not in partitions_to_check:
|
||||
+ partitions_to_check[part.path] = part
|
||||
+
|
||||
+ for path, part in partitions_to_check.items():
|
||||
+ part_dev = storage.devicetree.get_device_by_path(path)
|
||||
+ if part_dev and part_dev.protected:
|
||||
+ log.debug("Not checking protected %s for being mounted, assuming live "
|
||||
+ "image mount", path)
|
||||
+ return
|
||||
+
|
||||
+ if part.busy:
|
||||
+ report_error(_("%s is currently mounted and cannot be used for the "
|
||||
+ "installation. Please unmount it and retry.") % path)
|
||||
|
||||
|
||||
def verify_lvm_destruction(storage, constraints, report_error, report_warning):
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
From 76d20274ea13439bdfa277aa18a99a1ee9a61d1c Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Slavik <vslavik@redhat.com>
|
||||
Date: Mon, 3 Aug 2020 15:05:53 +0200
|
||||
Subject: [PATCH] Create ssh user using only existing fields (#1860058)
|
||||
|
||||
This fixes the bug where "homedir" and other fields do not exist on
|
||||
F24_SshPwData and no user is created for SSH access to installation
|
||||
environment.
|
||||
|
||||
Resolves: rhbz#1860058
|
||||
|
||||
Cherry-picked from df09030f0e7c8f350ba36ce99fa1bc33e4f45b6a
|
||||
---
|
||||
utils/handle-sshpw | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/utils/handle-sshpw b/utils/handle-sshpw
|
||||
index 0918610be..fc4726d88 100755
|
||||
--- a/utils/handle-sshpw
|
||||
+++ b/utils/handle-sshpw
|
||||
@@ -47,8 +47,8 @@ for ud in userdata:
|
||||
users.set_user_password(username=ud.username, password=ud.password,
|
||||
is_crypted=ud.isCrypted, lock=ud.lock)
|
||||
else:
|
||||
- users.create_user(username=ud.username, password=ud.password, is_crypted=ud.isCrypted, lock=ud.lock,
|
||||
- homedir=ud.homedir, shell=ud.shell, gecos=ud.gecos, root="/")
|
||||
+ users.create_user(username=ud.username, password=ud.password, is_crypted=ud.isCrypted,
|
||||
+ lock=ud.lock, root="/")
|
||||
|
||||
if ud.sshkey:
|
||||
# Setup the account so that only the sshkey can be used
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,50 +0,0 @@
|
||||
From 5cb9170cafc3f81193fd872a21933a0fa2bd5f2c Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Mon, 6 Jul 2020 14:04:28 +0200
|
||||
Subject: [PATCH] Create the initial storage model during the initialization
|
||||
|
||||
After connecting all objects of the Storage service to signals, create
|
||||
the initial storage model. It will be propagated to all these objects.
|
||||
|
||||
Otherwise, the objects might raise the UnavailableStorageError exception.
|
||||
|
||||
(cherry-picked from a commit fabc9a0)
|
||||
---
|
||||
pyanaconda/modules/storage/storage.py | 4 ++++
|
||||
tests/nosetests/pyanaconda_tests/module_storage_test.py | 5 +++++
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/storage.py b/pyanaconda/modules/storage/storage.py
|
||||
index 9c5aff943..08254b0ce 100644
|
||||
--- a/pyanaconda/modules/storage/storage.py
|
||||
+++ b/pyanaconda/modules/storage/storage.py
|
||||
@@ -133,6 +133,10 @@ class StorageService(KickstartService):
|
||||
self.on_protected_devices_changed
|
||||
)
|
||||
|
||||
+ # After connecting modules to signals, create the initial
|
||||
+ # storage model. It will be propagated to all modules.
|
||||
+ self._set_storage(create_storage())
|
||||
+
|
||||
def _add_module(self, storage_module):
|
||||
"""Add a base kickstart module."""
|
||||
self._modules.append(storage_module)
|
||||
diff --git a/tests/nosetests/pyanaconda_tests/module_storage_test.py b/tests/nosetests/pyanaconda_tests/module_storage_test.py
|
||||
index 708981233..6bb1723d5 100644
|
||||
--- a/tests/nosetests/pyanaconda_tests/module_storage_test.py
|
||||
+++ b/tests/nosetests/pyanaconda_tests/module_storage_test.py
|
||||
@@ -120,6 +120,11 @@ class StorageInterfaceTestCase(unittest.TestCase):
|
||||
storage_reset_callback = Mock()
|
||||
self.storage_module.partitioning_reset.connect(storage_reset_callback)
|
||||
|
||||
+ self.assertIsNotNone(self.storage_module.storage)
|
||||
+ storage_changed_callback.assert_not_called()
|
||||
+ storage_reset_callback.assert_not_called()
|
||||
+
|
||||
+ self.storage_module._current_storage = None
|
||||
self.assertIsNotNone(self.storage_module.storage)
|
||||
storage_changed_callback.assert_called_once()
|
||||
storage_reset_callback.assert_not_called()
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,107 +0,0 @@
|
||||
From c9857a91ece047c0fc2df3554e625d15b4700818 Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Thu, 13 Aug 2020 13:04:14 +0200
|
||||
Subject: [PATCH] Differentiate between RAID levels of a device and its
|
||||
container
|
||||
|
||||
The current logic returned the same RAID level for the device and its container,
|
||||
but we expect that only one of them will have the RAID level set.
|
||||
---
|
||||
.../partitioning/interactive/add_device.py | 4 +-
|
||||
.../storage/partitioning/interactive/utils.py | 37 +++++++++++++++----
|
||||
2 files changed, 31 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/partitioning/interactive/add_device.py b/pyanaconda/modules/storage/partitioning/interactive/add_device.py
|
||||
index 82bb9917a..852cf8fbd 100644
|
||||
--- a/pyanaconda/modules/storage/partitioning/interactive/add_device.py
|
||||
+++ b/pyanaconda/modules/storage/partitioning/interactive/add_device.py
|
||||
@@ -24,7 +24,7 @@ from pyanaconda.modules.common.errors.configuration import StorageConfigurationE
|
||||
from pyanaconda.modules.common.structures.device_factory import DeviceFactoryRequest
|
||||
from pyanaconda.modules.common.task import Task
|
||||
from pyanaconda.modules.storage.partitioning.interactive.utils import \
|
||||
- get_device_raid_level_name, get_container_size_policy, get_device_factory_arguments
|
||||
+ get_container_raid_level_name, get_container_size_policy, get_device_factory_arguments
|
||||
from pyanaconda.core.storage import PARTITION_ONLY_FORMAT_TYPES
|
||||
|
||||
log = get_module_logger(__name__)
|
||||
@@ -141,7 +141,7 @@ class AddDeviceTask(Task):
|
||||
# Don't override user-initiated changes to a defined container.
|
||||
request.disks = [d.name for d in container.disks]
|
||||
request.container_encrypted = container.encrypted
|
||||
- request.container_raid_level = get_device_raid_level_name(container)
|
||||
+ request.container_raid_level = get_container_raid_level_name(container)
|
||||
request.container_size_policy = get_container_size_policy(container)
|
||||
|
||||
# The existing container has a name.
|
||||
diff --git a/pyanaconda/modules/storage/partitioning/interactive/utils.py b/pyanaconda/modules/storage/partitioning/interactive/utils.py
|
||||
index 04313eded..d3e56030a 100644
|
||||
--- a/pyanaconda/modules/storage/partitioning/interactive/utils.py
|
||||
+++ b/pyanaconda/modules/storage/partitioning/interactive/utils.py
|
||||
@@ -696,12 +696,6 @@ def get_device_raid_level(device):
|
||||
if hasattr(device, "data_level"):
|
||||
return device.data_level
|
||||
|
||||
- if hasattr(device, "volume"):
|
||||
- return device.volume.data_level
|
||||
-
|
||||
- if not hasattr(device, "vg") and hasattr(device, "lvs") and len(device.parents) == 1:
|
||||
- return get_device_raid_level(device.parents[0])
|
||||
-
|
||||
return None
|
||||
|
||||
|
||||
@@ -711,6 +705,33 @@ def get_device_raid_level_name(device):
|
||||
return raid_level.name if raid_level else ""
|
||||
|
||||
|
||||
+def get_container_raid_level(container):
|
||||
+ """Get the RAID level of the given container.
|
||||
+
|
||||
+ :param container: a container
|
||||
+ :return: a RAID level
|
||||
+ """
|
||||
+ # Try to get a RAID level of this device.
|
||||
+ raid_level = get_device_raid_level(container)
|
||||
+
|
||||
+ if raid_level:
|
||||
+ return raid_level
|
||||
+
|
||||
+ device = container.raw_device
|
||||
+
|
||||
+ # Or get a RAID level of the LVM container.
|
||||
+ if hasattr(device, "lvs") and len(device.parents) == 1:
|
||||
+ return get_container_raid_level(device.parents[0])
|
||||
+
|
||||
+ return None
|
||||
+
|
||||
+
|
||||
+def get_container_raid_level_name(device):
|
||||
+ """Get the RAID level name of the given container."""
|
||||
+ raid_level = get_container_raid_level(device)
|
||||
+ return raid_level.name if raid_level else ""
|
||||
+
|
||||
+
|
||||
def collect_file_system_types(device):
|
||||
"""Collect supported file system types for the given device.
|
||||
|
||||
@@ -855,7 +876,7 @@ def set_container_data(request: DeviceFactoryRequest, container):
|
||||
request.container_spec = container.name
|
||||
request.container_name = container.name
|
||||
request.container_encrypted = container.encrypted
|
||||
- request.container_raid_level = get_device_raid_level_name(container)
|
||||
+ request.container_raid_level = get_container_raid_level_name(container)
|
||||
request.container_size_policy = get_container_size_policy(container)
|
||||
|
||||
if request.container_encrypted:
|
||||
@@ -1100,7 +1121,7 @@ def _destroy_device(storage, device):
|
||||
disks=container.disks,
|
||||
container_name=container.name,
|
||||
container_encrypted=container.encrypted,
|
||||
- container_raid_level=get_device_raid_level(container),
|
||||
+ container_raid_level=get_container_raid_level(container),
|
||||
container_size=container.size_policy,
|
||||
)
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
From 681285fff08169abd175beafae9e4144735e8cd9 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Fri, 21 Aug 2020 12:59:03 +0200
|
||||
Subject: [PATCH] Do not mount as RW in Dracut
|
||||
|
||||
Dracut do not have reason to mount sources as RW it's more that it wasn't
|
||||
specified and until recently we just did not bother. However, we changed the
|
||||
logic that installation sources in stage2 environment does not re-using mounts
|
||||
from the Dracut so this will now fail to set the environment because you can't
|
||||
mount one thing as RW and RO at once.
|
||||
|
||||
Resolves: rhbz#1871049
|
||||
(cherry picked from commit 408ae390c9ed7d14ad6c51979a18d839720e8be6)
|
||||
---
|
||||
dracut/anaconda-diskroot | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dracut/anaconda-diskroot b/dracut/anaconda-diskroot
|
||||
index 7e52e052b..8846b1108 100755
|
||||
--- a/dracut/anaconda-diskroot
|
||||
+++ b/dracut/anaconda-diskroot
|
||||
@@ -64,6 +64,6 @@ if [ -e /tmp/dd_interactive -a ! -e /tmp/dd.done ]; then
|
||||
fi
|
||||
|
||||
info "anaconda using disk root at $dev"
|
||||
-mount $dev $repodir || warn "Couldn't mount $dev"
|
||||
+mount -o ro $dev $repodir || warn "Couldn't mount $dev"
|
||||
anaconda_live_root_dir $repodir $path
|
||||
run_checkisomd5 $dev
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,98 +0,0 @@
|
||||
From e0351e363baedcf788d7ff39fea282885229b4dc Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Fri, 27 Nov 2020 16:46:59 +0100
|
||||
Subject: [PATCH] Don't enter spokes after we leave the Summary hub
|
||||
|
||||
If we decide to automatically leave the Summary hub and start the installation,
|
||||
don't allow to enter spokes from the Summary hub anymore. There might be some
|
||||
unprocessed callbacks in the even queue.
|
||||
|
||||
Resolved: rhzb#1866022
|
||||
---
|
||||
pyanaconda/ui/gui/hubs/__init__.py | 26 +++++++++++++++-----------
|
||||
1 file changed, 15 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/hubs/__init__.py b/pyanaconda/ui/gui/hubs/__init__.py
|
||||
index ee30fd004..81979470b 100644
|
||||
--- a/pyanaconda/ui/gui/hubs/__init__.py
|
||||
+++ b/pyanaconda/ui/gui/hubs/__init__.py
|
||||
@@ -85,10 +85,11 @@ class Hub(GUIObject, common.Hub):
|
||||
GUIObject.__init__(self, data)
|
||||
common.Hub.__init__(self, storage, payload)
|
||||
|
||||
- # enable the autoContinue feature if we are in kickstart
|
||||
+ # enable the auto continue feature if we are in kickstart
|
||||
# mode, but if the user interacts with the hub, it will be
|
||||
# disabled again
|
||||
- self._autoContinue = flags.automatedInstall
|
||||
+ self._auto_continue = flags.automatedInstall
|
||||
+ self._click_continue = False
|
||||
|
||||
self._hubs_collection.append(self)
|
||||
self.timeout = None
|
||||
@@ -262,7 +263,7 @@ class Hub(GUIObject, common.Hub):
|
||||
# If this is a kickstart, consider the user to be warned and
|
||||
# let them continue anyway, manually
|
||||
if flags.automatedInstall:
|
||||
- self._autoContinue = False
|
||||
+ self._auto_continue = False
|
||||
self._checker_ignore = True
|
||||
else:
|
||||
warning = _("Please complete items marked with this icon before continuing to the next step.")
|
||||
@@ -301,7 +302,6 @@ class Hub(GUIObject, common.Hub):
|
||||
log.debug("no spokes available on %s, continuing automatically", self)
|
||||
gtk_call_once(self.window.emit, "continue-clicked")
|
||||
|
||||
- click_continue = False
|
||||
# Grab all messages that may have appeared since last time this method ran.
|
||||
while True:
|
||||
try:
|
||||
@@ -357,9 +357,9 @@ class Hub(GUIObject, common.Hub):
|
||||
|
||||
if self.continuePossible:
|
||||
if self._inSpoke:
|
||||
- self._autoContinue = False
|
||||
- elif self._autoContinue:
|
||||
- click_continue = True
|
||||
+ self._auto_continue = False
|
||||
+ elif self._auto_continue:
|
||||
+ self._click_continue = True
|
||||
|
||||
elif code == hubQ.HUB_CODE_MESSAGE:
|
||||
spoke.selector.set_property("status", args[1])
|
||||
@@ -368,9 +368,9 @@ class Hub(GUIObject, common.Hub):
|
||||
q.task_done()
|
||||
|
||||
# queue is now empty, should continue be clicked?
|
||||
- if self._autoContinue and click_continue and self.window.get_may_continue():
|
||||
+ if self._auto_continue and self._click_continue and self.window.get_may_continue():
|
||||
# enqueue the emit to the Gtk message queue
|
||||
- log.debug("_autoContinue clicking continue button")
|
||||
+ log.debug("automatically clicking continue button")
|
||||
gtk_call_once(self.window.emit, "continue-clicked")
|
||||
|
||||
return True
|
||||
@@ -410,14 +410,18 @@ class Hub(GUIObject, common.Hub):
|
||||
if selector:
|
||||
selector.grab_focus()
|
||||
|
||||
+ # The automated kickstart installation already continues. Nothing to do.
|
||||
+ if self._click_continue:
|
||||
+ return
|
||||
+
|
||||
# On automated kickstart installs, our desired behavior is to display
|
||||
# the hub while background processes work, then skip to the progress
|
||||
# hub immediately after everything's done.
|
||||
# However if the user proves his intent to change the kickstarted
|
||||
# values by entering any of the spokes, we need to disable the
|
||||
- # autoContinue feature and wait for the user to explicitly state
|
||||
+ # auto continue feature and wait for the user to explicitly state
|
||||
# that he is done configuring by pressing the continue button.
|
||||
- self._autoContinue = False
|
||||
+ self._auto_continue = False
|
||||
|
||||
# Enter the spoke
|
||||
self._inSpoke = True
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
From 0c3cb13730730da2edcc6567bec8256eee9b1770 Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Thu, 13 Aug 2020 12:39:40 +0200
|
||||
Subject: [PATCH] Don't generate container data for non-container device types
|
||||
|
||||
If the current device type is not a container device type, don't generate
|
||||
container data for the device factory request.
|
||||
---
|
||||
pyanaconda/modules/storage/partitioning/interactive/utils.py | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/partitioning/interactive/utils.py b/pyanaconda/modules/storage/partitioning/interactive/utils.py
|
||||
index 0057abd6e..04313eded 100644
|
||||
--- a/pyanaconda/modules/storage/partitioning/interactive/utils.py
|
||||
+++ b/pyanaconda/modules/storage/partitioning/interactive/utils.py
|
||||
@@ -808,6 +808,7 @@ def generate_device_factory_request(storage, device) -> DeviceFactoryRequest:
|
||||
if device_type is None:
|
||||
raise UnsupportedDeviceError("Unsupported type of {}.".format(device.name))
|
||||
|
||||
+ # Generate the device data.
|
||||
request = DeviceFactoryRequest()
|
||||
request.device_spec = device.name
|
||||
request.device_name = getattr(device.raw_device, "lvname", device.raw_device.name)
|
||||
@@ -828,6 +829,10 @@ def generate_device_factory_request(storage, device) -> DeviceFactoryRequest:
|
||||
|
||||
request.disks = [d.name for d in disks]
|
||||
|
||||
+ if request.device_type not in CONTAINER_DEVICE_TYPES:
|
||||
+ return request
|
||||
+
|
||||
+ # Generate the container data.
|
||||
factory = devicefactory.get_device_factory(
|
||||
storage,
|
||||
device_type=device_type,
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,149 +0,0 @@
|
||||
From 5d81a7faa67bc065a6e309561865d1682abbcee4 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Pitt <mpitt@redhat.com>
|
||||
Date: Wed, 7 Oct 2020 07:26:18 +0200
|
||||
Subject: [PATCH] Fix SECTION headers in docstrings
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Make them coincide with the class names. The missing "Anaconda" prefix
|
||||
causes a build failure with gobject-introspection ≥ 1.61.1 due to [1]:
|
||||
|
||||
Namespace conflict: DocSection('BaseWindow')
|
||||
|
||||
See https://bugzilla.redhat.com/show_bug.cgi?id=1885825 for some
|
||||
details.
|
||||
|
||||
[1] https://gitlab.gnome.org/GNOME/gobject-introspection/-/commit/346c0690fe62f614ecb1f55857ea72939d9c0f83
|
||||
---
|
||||
widgets/src/BaseStandalone.c | 2 +-
|
||||
widgets/src/BaseWindow.c | 2 +-
|
||||
widgets/src/DiskOverview.c | 2 +-
|
||||
widgets/src/HubWindow.c | 2 +-
|
||||
widgets/src/LayoutIndicator.c | 2 +-
|
||||
widgets/src/MountpointSelector.c | 2 +-
|
||||
widgets/src/SpokeSelector.c | 2 +-
|
||||
widgets/src/SpokeWindow.c | 2 +-
|
||||
widgets/src/StandaloneWindow.c | 2 +-
|
||||
9 files changed, 9 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/widgets/src/BaseStandalone.c b/widgets/src/BaseStandalone.c
|
||||
index 361f94d..ae84bfc 100644
|
||||
--- a/widgets/src/BaseStandalone.c
|
||||
+++ b/widgets/src/BaseStandalone.c
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "intl.h"
|
||||
|
||||
/**
|
||||
- * SECTION: BaseStandalone
|
||||
+ * SECTION: AnacondaBaseStandalone
|
||||
* @title: AnacondaBaseStandalone
|
||||
* @short_description: Abstract base class for standalone Anaconda windows.
|
||||
*
|
||||
diff --git a/widgets/src/BaseWindow.c b/widgets/src/BaseWindow.c
|
||||
index 203d4a7..35a8fe0 100644
|
||||
--- a/widgets/src/BaseWindow.c
|
||||
+++ b/widgets/src/BaseWindow.c
|
||||
@@ -30,7 +30,7 @@
|
||||
#include <atk/atk.h>
|
||||
|
||||
/**
|
||||
- * SECTION: BaseWindow
|
||||
+ * SECTION: AnacondaBaseWindow
|
||||
* @title: AnacondaBaseWindow
|
||||
* @short_description: Top-level, non-resizeable window
|
||||
*
|
||||
diff --git a/widgets/src/DiskOverview.c b/widgets/src/DiskOverview.c
|
||||
index c9e6e0b..2d5aec4 100644
|
||||
--- a/widgets/src/DiskOverview.c
|
||||
+++ b/widgets/src/DiskOverview.c
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "widgets-common.h"
|
||||
|
||||
/**
|
||||
- * SECTION: DiskOverview
|
||||
+ * SECTION: AnacondaDiskOverview
|
||||
* @title: AnacondaDiskOverview
|
||||
* @short_description: A widget that displays basic information about a disk
|
||||
*
|
||||
diff --git a/widgets/src/HubWindow.c b/widgets/src/HubWindow.c
|
||||
index 77d89e8..02ecde4 100644
|
||||
--- a/widgets/src/HubWindow.c
|
||||
+++ b/widgets/src/HubWindow.c
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "intl.h"
|
||||
|
||||
/**
|
||||
- * SECTION: HubWindow
|
||||
+ * SECTION: AnacondaHubWindow
|
||||
* @title: AnacondaHubWindow
|
||||
* @short_description: Window for displaying a Hub
|
||||
*
|
||||
diff --git a/widgets/src/LayoutIndicator.c b/widgets/src/LayoutIndicator.c
|
||||
index 6e83edd..9fcd983 100644
|
||||
--- a/widgets/src/LayoutIndicator.c
|
||||
+++ b/widgets/src/LayoutIndicator.c
|
||||
@@ -36,7 +36,7 @@
|
||||
#define DEFAULT_LABEL_MAX_CHAR_WIDTH 8
|
||||
|
||||
/**
|
||||
- * SECTION: LayoutIndicator
|
||||
+ * SECTION: AnacondaLayoutIndicator
|
||||
* @title: AnacondaLayoutIndicator
|
||||
* @short_description: An indicator of currently activated X layout
|
||||
*
|
||||
diff --git a/widgets/src/MountpointSelector.c b/widgets/src/MountpointSelector.c
|
||||
index e87ba6b..e4b1ad3 100644
|
||||
--- a/widgets/src/MountpointSelector.c
|
||||
+++ b/widgets/src/MountpointSelector.c
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "widgets-common.h"
|
||||
|
||||
/**
|
||||
- * SECTION: MountpointSelector
|
||||
+ * SECTION: AnacondaMountpointSelector
|
||||
* @title: AnacondaMountpointSelector
|
||||
* @short_description: A graphical way to select a mount point.
|
||||
*
|
||||
diff --git a/widgets/src/SpokeSelector.c b/widgets/src/SpokeSelector.c
|
||||
index 56db102..a6c680a 100644
|
||||
--- a/widgets/src/SpokeSelector.c
|
||||
+++ b/widgets/src/SpokeSelector.c
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "widgets-common.h"
|
||||
|
||||
/**
|
||||
- * SECTION: SpokeSelector
|
||||
+ * SECTION: AnacondaSpokeSelector
|
||||
* @title: AnacondaSpokeSelector
|
||||
* @short_description: A graphical way to enter a configuration spoke
|
||||
*
|
||||
diff --git a/widgets/src/SpokeWindow.c b/widgets/src/SpokeWindow.c
|
||||
index 226eb2c..7a958c6 100644
|
||||
--- a/widgets/src/SpokeWindow.c
|
||||
+++ b/widgets/src/SpokeWindow.c
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
/**
|
||||
- * SECTION: SpokeWindow
|
||||
+ * SECTION: AnacondaSpokeWindow
|
||||
* @title: AnacondaSpokeWindow
|
||||
* @short_description: Window for displaying single spokes
|
||||
*
|
||||
diff --git a/widgets/src/StandaloneWindow.c b/widgets/src/StandaloneWindow.c
|
||||
index 8a92e7b..cc31547 100644
|
||||
--- a/widgets/src/StandaloneWindow.c
|
||||
+++ b/widgets/src/StandaloneWindow.c
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
/**
|
||||
- * SECTION: StandaloneWindow
|
||||
+ * SECTION: AnacondaStandaloneWindow
|
||||
* @title: AnacondaStandaloneWindow
|
||||
* @short_description: Window for displaying standalone spokes
|
||||
*
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
From e0168180824ab04d8ee6d798efb039bf3d5555dc Mon Sep 17 00:00:00 2001
|
||||
From: Jan Stodola <honza.stodola@gmail.com>
|
||||
Date: Sat, 31 Oct 2020 22:16:35 +0100
|
||||
Subject: [PATCH] Fix checking ssl certificate for metadata (#1745064)
|
||||
|
||||
If the url kickstart command is used with the --noverifyssl option, the
|
||||
ssl certificate check needs to be disabled for the repository metadata.
|
||||
|
||||
Resolves: rhbz#1745064
|
||||
---
|
||||
pyanaconda/payload/dnf/payload.py | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pyanaconda/payload/dnf/payload.py b/pyanaconda/payload/dnf/payload.py
|
||||
index 623518c66..f146b0dce 100644
|
||||
--- a/pyanaconda/payload/dnf/payload.py
|
||||
+++ b/pyanaconda/payload/dnf/payload.py
|
||||
@@ -1677,7 +1677,8 @@ class DNFPayload(Payload):
|
||||
# - the path to a cert file
|
||||
# - True, to use the system's certificates
|
||||
# - False, to not verify
|
||||
- ssl_verify = data.ssl_configuration.ca_cert_path or conf.payload.verify_ssl
|
||||
+ ssl_verify = (data.ssl_configuration.ca_cert_path
|
||||
+ or (conf.payload.verify_ssl and data.ssl_verification_enabled))
|
||||
ssl_client_cert = data.ssl_configuration.client_cert_path or None
|
||||
ssl_client_key = data.ssl_configuration.client_key_path or None
|
||||
ssl_cert = (ssl_client_cert, ssl_client_key) if ssl_client_cert else None
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
From c3dbffacabc60f0149b142a1f6b3f29739e9288b Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Mon, 27 Jul 2020 18:13:30 +0200
|
||||
Subject: [PATCH] Fix crash on first entering of source spoke
|
||||
|
||||
This is called by removing treeinfo repositories which happens thanks to the
|
||||
initialization of the spoke and selecting first line. Just let everything go
|
||||
because the repository is added later again (or at least it seems to be working
|
||||
like that).
|
||||
|
||||
Related: rhbz#1851207
|
||||
(cherry picked from commit 5136a4f961c98fec373033027502fba8b409c04d)
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/installation_source.py | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/installation_source.py b/pyanaconda/ui/gui/spokes/installation_source.py
|
||||
index 0bd3b6938..7ed95c51d 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/installation_source.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/installation_source.py
|
||||
@@ -1639,10 +1639,12 @@ class SourceSpoke(NormalSpoke, GUISpokeInputCheckHandler, SourceSwitchHandler):
|
||||
|
||||
# Remove the input validation checks for this repo
|
||||
repo = self._repo_store[itr][REPO_OBJ]
|
||||
- self.remove_check(self._repo_checks[repo.repo_id].name_check)
|
||||
- self.remove_check(self._repo_checks[repo.repo_id].url_check)
|
||||
- self.remove_check(self._repo_checks[repo.repo_id].proxy_check)
|
||||
- del self._repo_checks[repo.repo_id]
|
||||
+ # avoid crash when the source is changed because of initialization
|
||||
+ if repo.repo_id in self._repo_checks:
|
||||
+ self.remove_check(self._repo_checks[repo.repo_id].name_check)
|
||||
+ self.remove_check(self._repo_checks[repo.repo_id].url_check)
|
||||
+ self.remove_check(self._repo_checks[repo.repo_id].proxy_check)
|
||||
+ del self._repo_checks[repo.repo_id]
|
||||
|
||||
self._repo_store.remove(itr)
|
||||
if len(self._repo_store) == 0:
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,56 +0,0 @@
|
||||
From 373da9db5d1c7d138f87abfb69165bd9de413a41 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Mon, 13 Jul 2020 14:53:42 +0200
|
||||
Subject: [PATCH] Fix creating cached LVs on encrypted PVs
|
||||
|
||||
We need to get the child device for encrypted PVs because the PV
|
||||
devices from kickstart are the underlying partitions, not the
|
||||
lvmpv formatted LUKS devices.
|
||||
|
||||
Resolves: rhbz#1855973
|
||||
---
|
||||
.../partitioning/custom/custom_partitioning.py | 14 ++++++++++++--
|
||||
1 file changed, 12 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/partitioning/custom/custom_partitioning.py b/pyanaconda/modules/storage/partitioning/custom/custom_partitioning.py
|
||||
index 754a48e2e..17c125dd6 100644
|
||||
--- a/pyanaconda/modules/storage/partitioning/custom/custom_partitioning.py
|
||||
+++ b/pyanaconda/modules/storage/partitioning/custom/custom_partitioning.py
|
||||
@@ -851,6 +851,16 @@ class CustomPartitioningTask(NonInteractivePartitioningTask):
|
||||
if data.logvol.lvList:
|
||||
grow_lvm(storage)
|
||||
|
||||
+ def _get_cache_pv_devices(self, devicetree, logvol_data):
|
||||
+ pv_devices = []
|
||||
+ for pvname in logvol_data.cache_pvs:
|
||||
+ pv = lookup_alias(devicetree, pvname)
|
||||
+ if pv.format.type == "luks":
|
||||
+ pv_devices.append(pv.children[0])
|
||||
+ else:
|
||||
+ pv_devices.append(pv)
|
||||
+ return pv_devices
|
||||
+
|
||||
def _execute_logvol_data(self, storage, data, logvol_data):
|
||||
"""Execute the logvol data.
|
||||
|
||||
@@ -927,7 +937,7 @@ class CustomPartitioningTask(NonInteractivePartitioningTask):
|
||||
|
||||
# If cache PVs specified, check that they belong to the same VG this LV is a member of
|
||||
if logvol_data.cache_pvs:
|
||||
- pv_devices = (lookup_alias(devicetree, pv) for pv in logvol_data.cache_pvs)
|
||||
+ pv_devices = self._get_cache_pv_devices(devicetree, logvol_data)
|
||||
if not all(pv in vg.pvs for pv in pv_devices):
|
||||
raise KickstartParseError(
|
||||
_("Cache PVs must belong to the same VG as the cached LV"),
|
||||
@@ -1096,7 +1106,7 @@ class CustomPartitioningTask(NonInteractivePartitioningTask):
|
||||
maxsize = None
|
||||
|
||||
if logvol_data.cache_size and logvol_data.cache_pvs:
|
||||
- pv_devices = [lookup_alias(devicetree, pv) for pv in logvol_data.cache_pvs]
|
||||
+ pv_devices = self._get_cache_pv_devices(devicetree, logvol_data)
|
||||
cache_size = Size("%d MiB" % logvol_data.cache_size)
|
||||
cache_mode = logvol_data.cache_mode or None
|
||||
cache_request = LVMCacheRequest(cache_size, pv_devices, cache_mode)
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
From bc8779761fe60313a1c754a6b24c2861e86a5e62 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Stodola <honza.stodola@gmail.com>
|
||||
Date: Sat, 14 Nov 2020 21:27:45 +0100
|
||||
Subject: [PATCH] Fix error in initrd: shift count out of range
|
||||
|
||||
anaconda_live_root_dir() can be called with just one argument (for example
|
||||
when booting boot.iso) and the following error is reported:
|
||||
|
||||
20:26:12,641 INFO dracut-initqueue:anaconda using disk root at /dev/sr0
|
||||
20:26:12,650 DEBUG kernel:ISO 9660 Extensions: Microsoft Joliet Level 3
|
||||
20:26:12,654 DEBUG kernel:ISO 9660 Extensions: RRIP_1991A
|
||||
20:26:12,654 INFO dracut-initqueue:/lib/anaconda-lib.sh: line 71: shift: 2: shift count out of range
|
||||
20:26:12,656 INFO dracut-initqueue:anaconda: found /run/install/repo//images/install.img
|
||||
|
||||
Remove the shift call, since it has no use.
|
||||
---
|
||||
dracut/anaconda-lib.sh | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dracut/anaconda-lib.sh b/dracut/anaconda-lib.sh
|
||||
index 3b86f3df9..0dc8c817e 100755
|
||||
--- a/dracut/anaconda-lib.sh
|
||||
+++ b/dracut/anaconda-lib.sh
|
||||
@@ -68,7 +68,7 @@ rulesfile="/etc/udev/rules.d/90-anaconda.rules"
|
||||
# try to find a usable runtime image from the repo mounted at $mnt.
|
||||
# if successful, move the mount(s) to $repodir/$isodir.
|
||||
anaconda_live_root_dir() {
|
||||
- local img="" iso="" srcdir="" mnt="$1" path="$2"; shift 2
|
||||
+ local img="" iso="" srcdir="" mnt="$1" path="$2"
|
||||
img=$(find_runtime $mnt/$path)
|
||||
if [ -n "$img" ]; then
|
||||
info "anaconda: found $img"
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
From a57be7d30897ecf301de673e41d1af975b4f593b Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Wed, 29 Jul 2020 14:12:51 +0200
|
||||
Subject: [PATCH] Fix issue that treeinfo repositories were never disabled
|
||||
|
||||
The add_repo() method always enable repository at the end. We should improve
|
||||
this correctly in the upstream to avoid the confusion.
|
||||
|
||||
Related: rhbz#1851207
|
||||
(cherry picked from commit d26f4e4cd054288360993220bc9cee4b7abf5ddc)
|
||||
---
|
||||
pyanaconda/payload/dnf/payload.py | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pyanaconda/payload/dnf/payload.py b/pyanaconda/payload/dnf/payload.py
|
||||
index 02a66cd25..56c52f54e 100644
|
||||
--- a/pyanaconda/payload/dnf/payload.py
|
||||
+++ b/pyanaconda/payload/dnf/payload.py
|
||||
@@ -1852,7 +1852,11 @@ class DNFPayload(Payload):
|
||||
repo.treeinfo_origin = True
|
||||
log.debug("Adding new treeinfo repository: %s enabled: %s",
|
||||
repo_md.name, repo_enabled)
|
||||
- self.add_repo(repo)
|
||||
+
|
||||
+ if repo_enabled:
|
||||
+ self.add_repo(repo)
|
||||
+ else:
|
||||
+ self.add_disabled_repo(repo)
|
||||
|
||||
def _cleanup_old_treeinfo_repositories(self):
|
||||
"""Remove all old treeinfo repositories before loading new ones.
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,79 +0,0 @@
|
||||
From 6317147760315ebc269470b3fdb3f66eaeefe9b2 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Fri, 19 Jun 2020 13:24:57 +0200
|
||||
Subject: [PATCH] Fix issue when NFS path is pointing directly to ISO
|
||||
(#1848718)
|
||||
|
||||
This is totally my fault... The problem is that I thought that this will happen
|
||||
when mounting and finding the ISO but not for the NFS mount. NFS mount can't be
|
||||
done for an ISO image but only for the directory.
|
||||
|
||||
Resolves: rhbz#1848718
|
||||
Resolves: rhbz#1849083
|
||||
|
||||
Reported-by: Adam Williamson <awilliam@redhat.com>
|
||||
---
|
||||
.../payloads/source/nfs/initialization.py | 28 ++++++++++++++++---
|
||||
1 file changed, 24 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/payloads/source/nfs/initialization.py b/pyanaconda/modules/payloads/source/nfs/initialization.py
|
||||
index 99601bf32..f21c641ea 100644
|
||||
--- a/pyanaconda/modules/payloads/source/nfs/initialization.py
|
||||
+++ b/pyanaconda/modules/payloads/source/nfs/initialization.py
|
||||
@@ -19,6 +19,7 @@ import os.path
|
||||
|
||||
from pyanaconda.anaconda_loggers import get_module_logger
|
||||
from pyanaconda.core.payload import parse_nfs_url
|
||||
+from pyanaconda.core.util import join_paths
|
||||
from pyanaconda.modules.common.errors.payload import SourceSetupError
|
||||
from pyanaconda.modules.common.task import Task
|
||||
from pyanaconda.modules.payloads.source.utils import find_and_mount_iso_image, \
|
||||
@@ -54,12 +55,16 @@ class SetUpNFSSourceTask(Task):
|
||||
mount_point
|
||||
))
|
||||
|
||||
+ options, host, path = parse_nfs_url(self._url)
|
||||
+ path, image = self._split_iso_from_path(path)
|
||||
try:
|
||||
- self._mount_nfs()
|
||||
+ self._mount_nfs(host, options, path)
|
||||
except PayloadSetupError:
|
||||
raise SourceSetupError("Could not mount NFS url '{}'".format(self._url))
|
||||
|
||||
- iso_name = find_and_mount_iso_image(self._device_mount, self._iso_mount)
|
||||
+ iso_source_path = join_paths(self._device_mount, image) if image else self._device_mount
|
||||
+
|
||||
+ iso_name = find_and_mount_iso_image(iso_source_path, self._iso_mount)
|
||||
|
||||
if iso_name:
|
||||
log.debug("Using the ISO '%s' mounted at '%s'.", iso_name, self._iso_mount)
|
||||
@@ -74,9 +79,24 @@ class SetUpNFSSourceTask(Task):
|
||||
raise SourceSetupError(
|
||||
"Nothing useful found for NFS source at {}".format(self._url))
|
||||
|
||||
- def _mount_nfs(self):
|
||||
- options, host, path = parse_nfs_url(self._url)
|
||||
+ @staticmethod
|
||||
+ def _split_iso_from_path(path):
|
||||
+ """Split ISO from NFS path.
|
||||
+
|
||||
+ NFS path could also contain pointer to ISO which should be mounted. Problem of this
|
||||
+ is that NFS path with ISO cannot be mounted as NFS mount. We have to split these
|
||||
+ before mount.
|
||||
+
|
||||
+ :param path: path on the NFS server which could point to ISO
|
||||
+ :return: tuple of path, iso_file_name; is_file_name is empty if no ISO is part of the path
|
||||
+ :rtype: tuple (str, str)
|
||||
+ """
|
||||
+ if path.endswith(".iso"):
|
||||
+ return path.rsplit("/", maxsplit=1)
|
||||
+
|
||||
+ return path, ""
|
||||
|
||||
+ def _mount_nfs(self, host, options, path):
|
||||
if not options:
|
||||
options = "nolock"
|
||||
elif "nolock" not in options:
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
From 49f6e0e64accb5a1e6590bb08f7986fe7eaec2de Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Thu, 29 Oct 2020 10:08:09 +0100
|
||||
Subject: [PATCH] Fix issue when ns_info cannot be retrieved for NVDimm
|
||||
namespace
|
||||
|
||||
If we don't skip this part the uncaught exception will raise because we
|
||||
are
|
||||
trying to concatenate string and None types.
|
||||
|
||||
This is happening when NVDIMM namespace is set to DEVDAX mode. In this
|
||||
mode
|
||||
there is no device to be returned so we will got None from blivet.
|
||||
|
||||
Resolves: rhbz#1891827
|
||||
(cherry picked from commit 6afc375b164a802e26802ec4ba54d3446c078091)
|
||||
---
|
||||
pyanaconda/modules/storage/nvdimm/nvdimm.py | 9 +++++++--
|
||||
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/nvdimm/nvdimm.py b/pyanaconda/modules/storage/nvdimm/nvdimm.py
|
||||
index 4476dd1..5b9c9dc 100644
|
||||
--- a/pyanaconda/modules/storage/nvdimm/nvdimm.py
|
||||
+++ b/pyanaconda/modules/storage/nvdimm/nvdimm.py
|
||||
@@ -101,6 +101,12 @@ class NVDIMMModule(KickstartBaseModule):
|
||||
devices_to_ignore = set()
|
||||
|
||||
for ns_name, ns_info in nvdimm.namespaces.items():
|
||||
+ # this is happening when namespace is set to DEVDAX mode - block device is not present
|
||||
+ if ns_info.blockdev is None:
|
||||
+ log.debug("%s will be skipped - NVDIMM namespace block device information "
|
||||
+ "can't be retrieved", ns_name)
|
||||
+ continue
|
||||
+
|
||||
info = udev.get_device(device_node="/dev/" + ns_info.blockdev)
|
||||
|
||||
if info and udev.device_get_format(info) == "iso9660":
|
||||
@@ -116,8 +122,7 @@ class NVDIMMModule(KickstartBaseModule):
|
||||
else:
|
||||
continue
|
||||
|
||||
- if ns_info.blockdev:
|
||||
- devices_to_ignore.add(ns_info.blockdev)
|
||||
+ devices_to_ignore.add(ns_info.blockdev)
|
||||
|
||||
return devices_to_ignore
|
||||
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
From dac59c13424e403f73e3cad46e7412482b17f92a Mon Sep 17 00:00:00 2001
|
||||
From: Kai Kang <kai.kang@windriver.com>
|
||||
Date: Thu, 6 Aug 2020 17:09:25 +0800
|
||||
Subject: [PATCH] Fix kickstart file error with user groups
|
||||
|
||||
When fill the "Group Membership" in "ADVANCED USER CONFIGURATION"
|
||||
dialog with the provided example text:
|
||||
|
||||
wheel, my-team (1245), project-x (29935)
|
||||
|
||||
It keeps the spaces between group name(project-x) and group id('(29935)'),
|
||||
and then write them to kickstart file. When boot anaconda with the kickstart
|
||||
file, it fails with:
|
||||
|
||||
| unrecognzed arguments: (1245),project-x (29935)
|
||||
|
||||
Filter out the spaces between group name and group id to avoid such
|
||||
issue.
|
||||
|
||||
Signed-off-by: Kai Kang <kai.kang@windriver.com>
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/user.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/user.py b/pyanaconda/ui/gui/spokes/user.py
|
||||
index 82fbdc8f8..05e01f8a6 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/user.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/user.py
|
||||
@@ -157,7 +157,7 @@ class AdvancedUserDialog(GUIObject, GUIDialogInputCheckHandler):
|
||||
self.user.gid = USER_GID_NOT_SET
|
||||
|
||||
# ''.split(',') returns [''] instead of [], which is not what we want
|
||||
- self.user.groups = [g.strip() for g in self._tGroups.get_text().split(",") if g]
|
||||
+ self.user.groups = [''.join(g.split()) for g in self._tGroups.get_text().split(",") if g]
|
||||
|
||||
# Send ready signal to main event loop
|
||||
hubQ.send_ready(self.__class__.__name__, False)
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
From 1e873f5084f84e16c5d26b65f29ba401ee7f7f94 Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Slavik <vslavik@redhat.com>
|
||||
Date: Wed, 3 Jun 2020 15:54:00 +0200
|
||||
Subject: [PATCH] Fix more SElinux contexts
|
||||
|
||||
Apparently we have them wrong in /boot/loader/entries and /etc/dnf/modules.d/
|
||||
See the linmked bugs for more details. This is a bit workaroundish, but works.
|
||||
|
||||
Resolves: rhbz#1775975
|
||||
Resolves: rhbz#1834189
|
||||
---
|
||||
data/post-scripts/80-setfilecons.ks | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/data/post-scripts/80-setfilecons.ks b/data/post-scripts/80-setfilecons.ks
|
||||
index d6f183ce8..f08e308e3 100644
|
||||
--- a/data/post-scripts/80-setfilecons.ks
|
||||
+++ b/data/post-scripts/80-setfilecons.ks
|
||||
@@ -13,7 +13,9 @@ restorecon -ir /etc/sysconfig/network-scripts /etc/lvm /etc/X11/xorg.conf.d \
|
||||
/var/lib /var/lib/iscsi /var/lock /var/log /var/spool \
|
||||
/var/cache/yum \
|
||||
/dev \
|
||||
- /root
|
||||
+ /root \
|
||||
+ /boot \
|
||||
+ /etc/dnf/modules.d
|
||||
|
||||
# Also relabel the OSTree variants of the traditional mounts if present
|
||||
restorecon -ir /var/roothome /var/home /var/opt /var/srv /var/media /var/mnt
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
From 1f384563fd5aa4070cd0b75a6bcaee1648884499 Mon Sep 17 00:00:00 2001
|
||||
From: Radek Vykydal <rvykydal@redhat.com>
|
||||
Date: Thu, 4 Jun 2020 13:21:53 +0200
|
||||
Subject: [PATCH] Fix passing of arguments when creating dracut arguments for
|
||||
FCoE
|
||||
|
||||
Resolves: rhbz#1843741
|
||||
|
||||
Port of https://github.com/rhinstaller/anaconda/pull/2644
|
||||
---
|
||||
pyanaconda/modules/storage/bootloader/base.py | 10 ++++++++--
|
||||
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/bootloader/base.py b/pyanaconda/modules/storage/bootloader/base.py
|
||||
index 9ec3def57..4711513ee 100644
|
||||
--- a/pyanaconda/modules/storage/bootloader/base.py
|
||||
+++ b/pyanaconda/modules/storage/bootloader/base.py
|
||||
@@ -792,19 +792,25 @@ class BootLoader(object):
|
||||
network_args = []
|
||||
ibft = False
|
||||
nic = ""
|
||||
+ host_address = dep.host_address or ""
|
||||
if isinstance(dep, blivet.devices.iScsiDiskDevice):
|
||||
if dep.iface == "default" or ":" in dep.iface:
|
||||
node = _get_iscsi_node_from_device(dep)
|
||||
if iscsi_proxy.IsNodeFromIbft(Node.to_structure(node)):
|
||||
ibft = True
|
||||
else:
|
||||
- nic = iface_for_host_ip(dep.host_address)
|
||||
+ nic = iface_for_host_ip(host_address)
|
||||
else:
|
||||
nic = iscsi_proxy.GetInterface(dep.iface)
|
||||
else:
|
||||
nic = dep.nic
|
||||
if nic or ibft:
|
||||
- network_args = network_proxy.GetDracutArguments(nic, dep.host_address, "", ibft)
|
||||
+ network_args = network_proxy.GetDracutArguments(
|
||||
+ nic,
|
||||
+ host_address,
|
||||
+ "",
|
||||
+ ibft
|
||||
+ )
|
||||
|
||||
self.boot_args.update(network_args)
|
||||
self.dracut_args.update(network_args)
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
From 9858b6e456630d5bdad5b6084c87e60749964f26 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Thu, 11 Jun 2020 16:56:07 +0200
|
||||
Subject: [PATCH] Fix regression reading kernel list when collecting
|
||||
configurations (#1846156)
|
||||
|
||||
We have to have payload prepared to be able to read list of kernels from the
|
||||
installation source. However, during transitioning to storage module we moved
|
||||
reading list of kernels to place where the installation tasks are collected
|
||||
instead of where they are executed.
|
||||
|
||||
Create a function which will read this list and execute everything later during
|
||||
the installation tasks execution.
|
||||
|
||||
Resolves: rhbz#1846156
|
||||
---
|
||||
pyanaconda/installation.py | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/installation.py b/pyanaconda/installation.py
|
||||
index a6ec79401..d9596bac8 100644
|
||||
--- a/pyanaconda/installation.py
|
||||
+++ b/pyanaconda/installation.py
|
||||
@@ -159,9 +159,12 @@ def _prepare_configuration(payload, ksdata):
|
||||
# been created, fixing the kernel root and subvol args and adding the missing initrd entry.
|
||||
bootloader_proxy = STORAGE.get_proxy(BOOTLOADER)
|
||||
|
||||
- if payload.type in PAYLOAD_LIVE_TYPES:
|
||||
+ def fix_btrfs_bootloader():
|
||||
btrfs_task = bootloader_proxy.FixBTRFSWithTask(payload.kernel_version_list)
|
||||
- generate_initramfs.append_dbus_tasks(STORAGE, [btrfs_task])
|
||||
+ sync_run_task(STORAGE.get_proxy(btrfs_task))
|
||||
+
|
||||
+ if payload.type in PAYLOAD_LIVE_TYPES:
|
||||
+ generate_initramfs.append(Task("Fix bootloader on BTRFS", fix_btrfs_bootloader))
|
||||
|
||||
# Invoking zipl should be the last thing done on a s390x installation (see #1652727).
|
||||
zipl_task = bootloader_proxy.FixZIPLWithTask()
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
From 2585d3380ebbd516757a2420486e68e2809961db Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Tue, 15 Sep 2020 17:25:28 +0200
|
||||
Subject: [PATCH] Fix the combo box for an URL type of additional repositories
|
||||
(#1879127)
|
||||
|
||||
In the commit ff9a7e1, we introduced new constants for the URL source types with
|
||||
values 'BASEURL', 'MIRRORLIST' and 'METALINK'. In the commit cc2c3d3, we started
|
||||
to use these constants in the Installation Source spoke and removed the old ones
|
||||
with values 'url', 'mirrorlist' and 'metalink'. We updated the combo box for the
|
||||
base repository, but forgot to update the combo box for additional repositories.
|
||||
|
||||
The combo box items have to have ids that match the values of the constants,
|
||||
otherwise the URL type of additional repositories will be always 'BASEURL'.
|
||||
|
||||
Resolves: rhbz#1879127
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/installation_source.glade | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/installation_source.glade b/pyanaconda/ui/gui/spokes/installation_source.glade
|
||||
index e53fa230c..bc07a4a7b 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/installation_source.glade
|
||||
+++ b/pyanaconda/ui/gui/spokes/installation_source.glade
|
||||
@@ -1296,9 +1296,9 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<items>
|
||||
- <item id="url" translatable="yes">repository URL</item>
|
||||
- <item id="mirrorlist" translatable="yes">mirrorlist</item>
|
||||
- <item id="metalink" translatable="yes">metalink</item>
|
||||
+ <item id="BASEURL" translatable="yes">repository URL</item>
|
||||
+ <item id="MIRRORLIST" translatable="yes">mirrorlist</item>
|
||||
+ <item id="METALINK" translatable="yes">metalink</item>
|
||||
</items>
|
||||
<signal name="changed" handler="on_repo_url_type_changed" swapped="no"/>
|
||||
</object>
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
From 98e011f1f8af900ed6f65432ad7466973d44735a Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Fri, 27 Nov 2020 14:33:31 +0100
|
||||
Subject: [PATCH] Fix the logic for enabling latest updates
|
||||
|
||||
Fix bugs introduced in the commit 4a2b8f2. The negation of the logic wasn't
|
||||
applied correctly. Without the fix, updates repositories are disabled when the
|
||||
updates are enabled.
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/installation_source.py | 8 +++-----
|
||||
1 file changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/installation_source.py b/pyanaconda/ui/gui/spokes/installation_source.py
|
||||
index 00a180613..e528d8662 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/installation_source.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/installation_source.py
|
||||
@@ -1085,7 +1085,7 @@ class SourceSpoke(NormalSpoke, GUISpokeInputCheckHandler, SourceSwitchHandler):
|
||||
uncheck it.
|
||||
"""
|
||||
self._updates_box.set_sensitive(self._mirror_active())
|
||||
- active = self._mirror_active() or self.payload.is_repo_enabled("updates")
|
||||
+ active = self._mirror_active() and self.payload.is_repo_enabled("updates")
|
||||
self._updates_radio_button.set_active(active)
|
||||
|
||||
@property
|
||||
@@ -1646,10 +1646,8 @@ class SourceSpoke(NormalSpoke, GUISpokeInputCheckHandler, SourceSwitchHandler):
|
||||
|
||||
def on_updatesRadioButton_toggled(self, button):
|
||||
"""Toggle the enable state of the updates repo."""
|
||||
- if self._updates_radio_button.get_active():
|
||||
- self.payload.set_updates_enabled(False)
|
||||
- else:
|
||||
- self.payload.set_updates_enabled(True)
|
||||
+ active = self._updates_radio_button.get_active()
|
||||
+ self.payload.set_updates_enabled(active)
|
||||
|
||||
# Refresh the metadata using the new set of repos
|
||||
self._updates_change = True
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
From b7ee1291870a0d6689ff6d81e1c50999f38cd6b7 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Fri, 21 Aug 2020 15:07:28 +0200
|
||||
Subject: [PATCH] Fix traceback when removing additional repository
|
||||
|
||||
I made a mistake by missing `not` in the condition. That way the repo removal as
|
||||
user action crashed Anaconda because variable which was not set was immediately
|
||||
used.
|
||||
|
||||
Unfortunately, I tested this just on the failing use-case and in that case it
|
||||
looked like it is working correctly (but didn't really).
|
||||
|
||||
Resolves: rhbz#1871037
|
||||
(cherry picked from commit a92428aa61f31d3f25786d4e90108d0d7751d680)
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/installation_source.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/installation_source.py b/pyanaconda/ui/gui/spokes/installation_source.py
|
||||
index 7ed95c51d..76631754b 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/installation_source.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/installation_source.py
|
||||
@@ -1629,7 +1629,7 @@ class SourceSpoke(NormalSpoke, GUISpokeInputCheckHandler, SourceSwitchHandler):
|
||||
:param repo_model_path: repo_model_path of what we can remove or None
|
||||
:type repo_model_path: repo_store repo_model_path
|
||||
"""
|
||||
- if repo_model_path is None:
|
||||
+ if repo_model_path is not None:
|
||||
itr = self._repo_store[repo_model_path].iter
|
||||
else:
|
||||
itr = self._repo_selection.get_selected()[1]
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
From 0f9873a2ffbf3a180a236c4f036e54520773f2ca Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Tue, 22 Sep 2020 16:28:48 +0200
|
||||
Subject: [PATCH] Fix traceback when starting installation with inst.console
|
||||
(no args)
|
||||
|
||||
None is the default value which would fail on os.path.basename call.
|
||||
---
|
||||
pyanaconda/modules/storage/bootloader/base.py | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/bootloader/base.py b/pyanaconda/modules/storage/bootloader/base.py
|
||||
index b1122287a..a8eb26cc7 100644
|
||||
--- a/pyanaconda/modules/storage/bootloader/base.py
|
||||
+++ b/pyanaconda/modules/storage/bootloader/base.py
|
||||
@@ -903,10 +903,16 @@ class BootLoader(object):
|
||||
|
||||
def _set_console(self):
|
||||
""" Set console options based on boot arguments. """
|
||||
- console = kernel_arguments.get("console", "")
|
||||
+ console = kernel_arguments.get("console")
|
||||
+
|
||||
+ if not console:
|
||||
+ return
|
||||
+
|
||||
console = os.path.basename(console)
|
||||
self.console, _x, self.console_options = console.partition(",")
|
||||
|
||||
+ log.debug("Console is set to %s with options '%s'", self.console, self.console_options)
|
||||
+
|
||||
def write_config_console(self, config):
|
||||
"""Write console-related configuration lines."""
|
||||
pass
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
From 8ab916a0fe7b46b20c3a51828600b4f7f207717a Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Slavik <vslavik@redhat.com>
|
||||
Date: Tue, 18 Aug 2020 15:23:49 +0200
|
||||
Subject: [PATCH] Handle exceptions from threads without new instances
|
||||
|
||||
It is not possible to instantiate some exceptions with just an instance as
|
||||
the only argument, for example UnicodeError and descendants. However, these
|
||||
days it is possible to raise directly with the provided instance, no need to
|
||||
instantiate the class. The instance also has the traceback already set, so no
|
||||
need to set it either.
|
||||
|
||||
The original apparently came to be so due to incrementally rewriting python2's
|
||||
3-argument form of raise. See also previous commits affecting this line,
|
||||
in chronological order: 07b7034, d16512e, a6085b8.
|
||||
|
||||
Resolves: rhbz#1835027
|
||||
---
|
||||
pyanaconda/threading.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pyanaconda/threading.py b/pyanaconda/threading.py
|
||||
index e0ab80229..d2327cf39 100644
|
||||
--- a/pyanaconda/threading.py
|
||||
+++ b/pyanaconda/threading.py
|
||||
@@ -168,7 +168,7 @@ class ThreadManager(object):
|
||||
with self._errors_lock:
|
||||
exc_info = self._errors.pop(name)
|
||||
if exc_info:
|
||||
- raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
|
||||
+ raise exc_info[1]
|
||||
|
||||
def in_main_thread(self):
|
||||
"""Return True if it is run in the main thread."""
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,101 +0,0 @@
|
||||
From 7982cf9937165ad34fe3c4bdf2cf2155a4f5e7f8 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Thu, 30 Jul 2020 13:25:28 +0200
|
||||
Subject: [PATCH] Keep treeinfo repositories disabled after payload reset
|
||||
|
||||
Without this change user can't disable repositories because they are
|
||||
reloaded and enabled automatically as new ones.
|
||||
|
||||
Related: rhbz#1851207
|
||||
(cherry picked from commit 0750143fca814b660eba719c2df597d3af5998f8)
|
||||
---
|
||||
pyanaconda/payload/dnf/payload.py | 33 +++++++++++++++++++++++++------
|
||||
1 file changed, 27 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/payload/dnf/payload.py b/pyanaconda/payload/dnf/payload.py
|
||||
index 227d32c82..02a66cd25 100644
|
||||
--- a/pyanaconda/payload/dnf/payload.py
|
||||
+++ b/pyanaconda/payload/dnf/payload.py
|
||||
@@ -1455,7 +1455,7 @@ class DNFPayload(Payload):
|
||||
log.info("Configuring the base repo")
|
||||
self.reset()
|
||||
|
||||
- self._cleanup_old_treeinfo_repositories()
|
||||
+ disabled_treeinfo_repo_names = self._cleanup_old_treeinfo_repositories()
|
||||
|
||||
# Find the source and its type.
|
||||
source_proxy = self.get_source_proxy()
|
||||
@@ -1511,7 +1511,7 @@ class DNFPayload(Payload):
|
||||
base_repo_url = self._get_base_repo_location(install_tree_url)
|
||||
log.debug("releasever from %s is %s", base_repo_url, self._base.conf.releasever)
|
||||
|
||||
- self._load_treeinfo_repositories(base_repo_url)
|
||||
+ self._load_treeinfo_repositories(base_repo_url, disabled_treeinfo_repo_names)
|
||||
except configparser.MissingSectionHeaderError as e:
|
||||
log.error("couldn't set releasever from base repo (%s): %s", source_type, e)
|
||||
|
||||
@@ -1817,11 +1817,13 @@ class DNFPayload(Payload):
|
||||
log.debug("No base repository found in treeinfo file. Using installation tree root.")
|
||||
return install_tree_url
|
||||
|
||||
- def _load_treeinfo_repositories(self, base_repo_url):
|
||||
+ def _load_treeinfo_repositories(self, base_repo_url, repo_names_to_disable):
|
||||
"""Load new repositories from treeinfo file.
|
||||
|
||||
:param base_repo_url: base repository url. This is not saved anywhere when the function
|
||||
is called. It will be add to the existing urls if not None.
|
||||
+ :param repo_names_to_disable: list of repository names which should be disabled after load
|
||||
+ :type repo_names_to_disable: [str]
|
||||
"""
|
||||
if self._install_tree_metadata:
|
||||
existing_urls = []
|
||||
@@ -1838,11 +1840,18 @@ class DNFPayload(Payload):
|
||||
for repo_md in self._install_tree_metadata.get_metadata_repos():
|
||||
if repo_md.path not in existing_urls:
|
||||
repo_treeinfo = self._install_tree_metadata.get_treeinfo_for(repo_md.name)
|
||||
- repo_enabled = repo_treeinfo.type in enabled_repositories_from_treeinfo
|
||||
+
|
||||
+ # disable repositories disabled by user manually before
|
||||
+ if repo_md.name in repo_names_to_disable:
|
||||
+ repo_enabled = False
|
||||
+ else:
|
||||
+ repo_enabled = repo_treeinfo.type in enabled_repositories_from_treeinfo
|
||||
+
|
||||
repo = RepoData(name=repo_md.name, baseurl=repo_md.path,
|
||||
install=False, enabled=repo_enabled)
|
||||
repo.treeinfo_origin = True
|
||||
- log.debug("Adding new treeinfo repository %s", repo_md.name)
|
||||
+ log.debug("Adding new treeinfo repository: %s enabled: %s",
|
||||
+ repo_md.name, repo_enabled)
|
||||
self.add_repo(repo)
|
||||
|
||||
def _cleanup_old_treeinfo_repositories(self):
|
||||
@@ -1850,12 +1859,24 @@ class DNFPayload(Payload):
|
||||
|
||||
Find all repositories added from treeinfo file and remove them. After this step new
|
||||
repositories will be loaded from the new link.
|
||||
+
|
||||
+ :return: list of repository names which were disabled before removal
|
||||
+ :rtype: [str]
|
||||
"""
|
||||
+ disabled_repo_names = []
|
||||
+
|
||||
for ks_repo_name in self.addons:
|
||||
- if self.get_addon_repo(ks_repo_name).treeinfo_origin:
|
||||
+ repo = self.get_addon_repo(ks_repo_name)
|
||||
+ if repo.treeinfo_origin:
|
||||
log.debug("Removing old treeinfo repository %s", ks_repo_name)
|
||||
+
|
||||
+ if not repo.enabled:
|
||||
+ disabled_repo_names.append(ks_repo_name)
|
||||
+
|
||||
self.remove_repo(ks_repo_name)
|
||||
|
||||
+ return disabled_repo_names
|
||||
+
|
||||
def _write_dnf_repo(self, repo, repo_path):
|
||||
"""Write a repo object to a DNF repo.conf file.
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,101 +0,0 @@
|
||||
From b224f888c225d9735abaa82d0156ae5a4c38d4f5 Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Fri, 18 Sep 2020 15:13:14 +0200
|
||||
Subject: [PATCH] Never mount partitions on a disk with the iso9660 filesystem
|
||||
|
||||
Blivet doesn't recognize these partitions, so we mount the disk in stage2.
|
||||
However, it will fail if one of its partitions is already mounted, for example
|
||||
in stage1. Therefore, skip these partitions in the script that looks for a root
|
||||
image on devices and use the disk instead.
|
||||
|
||||
The boot.iso has the following structure:
|
||||
|
||||
NAME TYPE SIZE FSTYPE LABEL
|
||||
sda disk 8.8G iso9660 RHEL-8-3-0-BaseOS-x86_64
|
||||
|-sda1 part 8.8G iso9660 RHEL-8-3-0-BaseOS-x86_64
|
||||
`-sda2 part 10M vfat ANACONDA
|
||||
|
||||
And the following default boot options:
|
||||
|
||||
inst.stage2=hd:LABEL=RHEL-8-3-0-BaseOS-x86_64 rd.live.check quiet
|
||||
|
||||
Anaconda runs the anaconda-diskroot script for every device that matches the
|
||||
specification from the inst.stage2 option. In this example, it is sda and sda1,
|
||||
because both of them have the specified label RHEL-8-3-0-BaseOS-x86_64. With
|
||||
the fix, the script will detect that sda1 is a partition on a disk with the
|
||||
iso9660 filesystem and stop to process sda1. The script will succeed with sda.
|
||||
|
||||
We should never rely on the order of the devices.
|
||||
|
||||
(cherry-picked from a commit 301a09d)
|
||||
|
||||
Related: rhbz#1878784
|
||||
---
|
||||
dracut/anaconda-diskroot | 17 ++++++++++++++++-
|
||||
dracut/anaconda-lib.sh | 22 ++++++++++++++++++++++
|
||||
2 files changed, 38 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dracut/anaconda-diskroot b/dracut/anaconda-diskroot
|
||||
index 8846b1108..2797e6762 100755
|
||||
--- a/dracut/anaconda-diskroot
|
||||
+++ b/dracut/anaconda-diskroot
|
||||
@@ -41,7 +41,22 @@ dev="$1"
|
||||
path="$2" # optional, could be empty
|
||||
kickstart="$(getarg ks= inst.ks=)"
|
||||
|
||||
-[ -e "/dev/root" ] && exit 1 # we already have a root device!
|
||||
+# Log the device that triggered this job.
|
||||
+debug_msg "Trying to find a root image on the device $dev."
|
||||
+
|
||||
+# Do we already have a root device?
|
||||
+# Then do not run again.
|
||||
+[ -e "/dev/root" ] && exit 1
|
||||
+
|
||||
+# Skip partitions on a disk with the iso9660 filesystem. Blivet doesn't
|
||||
+# recognize these partitions, so we mount the disk in stage2. However, it
|
||||
+# will fail if one of its partitions is already mounted, for example here.
|
||||
+# Therefore, skip the partitions and use the disk to find our root image.
|
||||
+# See the bug 1878784.
|
||||
+if dev_is_on_disk_with_iso9660 "$dev"; then
|
||||
+ debug_msg "Skipping $dev on a disk with iso9660."
|
||||
+ exit 1
|
||||
+fi
|
||||
|
||||
# If we're waiting for a cdrom kickstart, the user might need to swap discs.
|
||||
# So if this is a CDROM drive, make a note of it, but don't mount it (yet).
|
||||
diff --git a/dracut/anaconda-lib.sh b/dracut/anaconda-lib.sh
|
||||
index e2ab7a205..3b86f3df9 100755
|
||||
--- a/dracut/anaconda-lib.sh
|
||||
+++ b/dracut/anaconda-lib.sh
|
||||
@@ -253,6 +253,28 @@ dev_is_cdrom() {
|
||||
udevadm info --query=property --name=$1 | grep -q 'ID_CDROM=1'
|
||||
}
|
||||
|
||||
+dev_is_on_disk_with_iso9660() {
|
||||
+ # Get the name of the device.
|
||||
+ local dev_name="${1}"
|
||||
+
|
||||
+ # Get the path of the device.
|
||||
+ local dev_path="$(udevadm info -q path --name ${dev_name})"
|
||||
+
|
||||
+ # Is the device a partition?
|
||||
+ udevadm info -q property --path ${dev_path} | grep -q 'DEVTYPE=partition' || return 1
|
||||
+
|
||||
+ # Get the path of the parent.
|
||||
+ local disk_path="${dev_path%/*}"
|
||||
+
|
||||
+ # Is the parent a disk?
|
||||
+ udevadm info -q property --path ${disk_path} | grep -q 'DEVTYPE=disk' || return 1
|
||||
+
|
||||
+ # Does the parent has the iso9660 filesystem?
|
||||
+ udevadm info -q property --path ${disk_path} | grep -q 'ID_FS_TYPE=iso9660' || return 1
|
||||
+
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
# dracut doesn't bring up the network unless:
|
||||
# a) $netroot is set (i.e. you have a network root device), or
|
||||
# b) /tmp/net.ifaces exists.
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
From 4766a00a9d67bfe93573e1160ac05fe9c8883aa9 Mon Sep 17 00:00:00 2001
|
||||
From: Javier Martinez Canillas <javierm@redhat.com>
|
||||
Date: Thu, 9 Jul 2020 15:51:23 +0200
|
||||
Subject: [PATCH] Only pass one initrd image to kexec
|
||||
|
||||
The kexec command line tool can only get a single initrd, but a boot entry
|
||||
can have multiple ones. For example the tuned package adds a variable that
|
||||
could be set to a second initrd image.
|
||||
|
||||
If that's the case, it will lead to the following error:
|
||||
|
||||
FileNotFoundError: [Errno 2] No such file or directory:
|
||||
'/mnt/sysroot/boot/initramfs-4.18.0-223.el8.x86_64.img $tuned_initrd'
|
||||
|
||||
Resolves: rhbz#1855290
|
||||
|
||||
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
|
||||
---
|
||||
pyanaconda/kexec.py | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/pyanaconda/kexec.py b/pyanaconda/kexec.py
|
||||
index 02033bb7e..37d2b4a14 100644
|
||||
--- a/pyanaconda/kexec.py
|
||||
+++ b/pyanaconda/kexec.py
|
||||
@@ -72,6 +72,11 @@ def run_grubby(args=None):
|
||||
if boot_info_fields:
|
||||
raise GrubbyInfoError("Missing values: %s" % ", ".join(boot_info_fields))
|
||||
|
||||
+ # There could be multiple initrd images defined for a boot entry, but
|
||||
+ # the kexec command line tool only supports passing a single initrd.
|
||||
+ if "initrd" in boot_info_args:
|
||||
+ boot_info_args["initrd"] = boot_info_args["initrd"].split(" ")[0]
|
||||
+
|
||||
boot_info = boot_info_class(**boot_info_args)
|
||||
log.info("grubby boot info for (%s): %s", args, boot_info)
|
||||
return boot_info
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,291 +0,0 @@
|
||||
From 39d3a894411e3069cdb14354509153028a48e6c5 Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Wed, 2 Sep 2020 13:40:36 +0200
|
||||
Subject: [PATCH] Propagate a lazy proxy of the storage model
|
||||
|
||||
The storage model for the partitioning modules should be always created lazily.
|
||||
When we reset the partitioning, the new model shouldn't be created until we try
|
||||
to work with it. Then we create a new copy of the storage model, hide disks that
|
||||
are not selected and possibly initialize empty disks.
|
||||
|
||||
There is a problem with modules that need to be able to work with the same copy
|
||||
of the storage model as the partitioning modules. At this moment, it is only the
|
||||
device tree module. The suggested solution is to propagate a lazy proxy of the
|
||||
storage model. It will not trigger the creation of the copy until we try to
|
||||
access the attributes of the storage model.
|
||||
|
||||
Basically, the device tree module always gets the storage model on demand from
|
||||
the storage property of the partitioning module.
|
||||
|
||||
Related: rhbz#1868577
|
||||
---
|
||||
pyanaconda/core/util.py | 37 +++++++
|
||||
.../modules/storage/partitioning/base.py | 28 ++++--
|
||||
.../module_part_interactive_test.py | 18 ++++
|
||||
tests/nosetests/pyanaconda_tests/util_test.py | 97 ++++++++++++++++++-
|
||||
4 files changed, 170 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/core/util.py b/pyanaconda/core/util.py
|
||||
index 4615f9fd8..60b6ff310 100644
|
||||
--- a/pyanaconda/core/util.py
|
||||
+++ b/pyanaconda/core/util.py
|
||||
@@ -1431,3 +1431,40 @@ def is_smt_enabled():
|
||||
except (IOError, ValueError):
|
||||
log.warning("Failed to detect SMT.")
|
||||
return False
|
||||
+
|
||||
+
|
||||
+class LazyObject(object):
|
||||
+ """The lazy object."""
|
||||
+
|
||||
+ def __init__(self, getter):
|
||||
+ """Create a proxy of an object.
|
||||
+
|
||||
+ The object might not exist until we call the given
|
||||
+ function. The function is called only when we try
|
||||
+ to access the attributes of the object.
|
||||
+
|
||||
+ The returned object is not cached in this class.
|
||||
+ We call the function every time.
|
||||
+
|
||||
+ :param getter: a function that returns the object
|
||||
+ """
|
||||
+ self._getter = getter
|
||||
+
|
||||
+ @property
|
||||
+ def _object(self):
|
||||
+ return self._getter()
|
||||
+
|
||||
+ def __eq__(self, other):
|
||||
+ return self._object == other
|
||||
+
|
||||
+ def __hash__(self):
|
||||
+ return self._object.__hash__()
|
||||
+
|
||||
+ def __getattr__(self, name):
|
||||
+ return getattr(self._object, name)
|
||||
+
|
||||
+ def __setattr__(self, name, value):
|
||||
+ if name in ("_getter", ):
|
||||
+ return super().__setattr__(name, value)
|
||||
+
|
||||
+ return setattr(self._object, name, value)
|
||||
diff --git a/pyanaconda/modules/storage/partitioning/base.py b/pyanaconda/modules/storage/partitioning/base.py
|
||||
index 989fa0a7b..c8b4b95ac 100644
|
||||
--- a/pyanaconda/modules/storage/partitioning/base.py
|
||||
+++ b/pyanaconda/modules/storage/partitioning/base.py
|
||||
@@ -17,12 +17,13 @@
|
||||
# License and may only be used or replicated with the express permission of
|
||||
# Red Hat, Inc.
|
||||
#
|
||||
-from abc import abstractmethod, abstractproperty
|
||||
+from abc import abstractmethod
|
||||
|
||||
from blivet.devices import PartitionDevice, TmpFSDevice, LVMLogicalVolumeDevice, \
|
||||
LVMVolumeGroupDevice, MDRaidArrayDevice, BTRFSDevice
|
||||
|
||||
from dasbus.server.publishable import Publishable
|
||||
+from pyanaconda.core.util import LazyObject
|
||||
from pyanaconda.modules.common.base.base import KickstartBaseModule
|
||||
from pyanaconda.modules.common.errors.storage import UnavailableStorageError
|
||||
from pyanaconda.anaconda_loggers import get_module_logger
|
||||
@@ -45,7 +46,8 @@ class PartitioningModule(KickstartBaseModule, Publishable):
|
||||
self._selected_disks = []
|
||||
self._device_tree_module = None
|
||||
|
||||
- @abstractproperty
|
||||
+ @property
|
||||
+ @abstractmethod
|
||||
def partitioning_method(self):
|
||||
"""Type of the partitioning method."""
|
||||
return None
|
||||
@@ -67,8 +69,22 @@ class PartitioningModule(KickstartBaseModule, Publishable):
|
||||
|
||||
return self._storage_playground
|
||||
|
||||
+ @property
|
||||
+ def lazy_storage(self):
|
||||
+ """The lazy storage model.
|
||||
+
|
||||
+ Provides a lazy access to the storage model. This property will not
|
||||
+ trigger a creation of the storage playground. The playground will be
|
||||
+ created on the first access of the storage attributes.
|
||||
+ """
|
||||
+ return LazyObject(lambda: self.storage)
|
||||
+
|
||||
def _create_storage_playground(self):
|
||||
"""Prepare the current storage model for partitioning."""
|
||||
+ log.debug(
|
||||
+ "Creating a new storage playground for %s with "
|
||||
+ "selected disks %s.", self, self._selected_disks
|
||||
+ )
|
||||
storage = self._current_storage.copy()
|
||||
storage.select_disks(self._selected_disks)
|
||||
return storage
|
||||
@@ -77,16 +93,10 @@ class PartitioningModule(KickstartBaseModule, Publishable):
|
||||
"""Update the current storage."""
|
||||
self._current_storage = storage
|
||||
|
||||
- if self._device_tree_module:
|
||||
- self._device_tree_module.on_storage_changed(self.storage)
|
||||
-
|
||||
def on_partitioning_reset(self):
|
||||
"""Drop the storage playground."""
|
||||
self._storage_playground = None
|
||||
|
||||
- if self._device_tree_module:
|
||||
- self._device_tree_module.on_storage_changed(self.storage)
|
||||
-
|
||||
def on_selected_disks_changed(self, selection):
|
||||
"""Keep the current disk selection."""
|
||||
self._selected_disks = selection
|
||||
@@ -100,7 +110,7 @@ class PartitioningModule(KickstartBaseModule, Publishable):
|
||||
|
||||
if not module:
|
||||
module = self._create_device_tree()
|
||||
- module.on_storage_changed(self.storage)
|
||||
+ module.on_storage_changed(self.lazy_storage)
|
||||
self._device_tree_module = module
|
||||
|
||||
return module
|
||||
diff --git a/tests/nosetests/pyanaconda_tests/module_part_interactive_test.py b/tests/nosetests/pyanaconda_tests/module_part_interactive_test.py
|
||||
index 13d33feab..32fe589b7 100644
|
||||
--- a/tests/nosetests/pyanaconda_tests/module_part_interactive_test.py
|
||||
+++ b/tests/nosetests/pyanaconda_tests/module_part_interactive_test.py
|
||||
@@ -71,6 +71,24 @@ class InteractivePartitioningInterfaceTestCase(unittest.TestCase):
|
||||
"""Test Method property."""
|
||||
self.assertEqual(self.interface.PartitioningMethod, PARTITIONING_METHOD_INTERACTIVE)
|
||||
|
||||
+ @patch_dbus_publish_object
|
||||
+ def lazy_storage_test(self, publisher):
|
||||
+ """Make sure that the storage playground is created lazily."""
|
||||
+ self.module.on_storage_changed(create_storage())
|
||||
+
|
||||
+ device_tree_module = self.module.get_device_tree()
|
||||
+ self.assertIsNone(self.module._storage_playground)
|
||||
+
|
||||
+ device_tree_module.get_disks()
|
||||
+ self.assertIsNotNone(self.module._storage_playground)
|
||||
+
|
||||
+ self.module.on_partitioning_reset()
|
||||
+ self.module.on_storage_changed(create_storage())
|
||||
+ self.assertIsNone(self.module._storage_playground)
|
||||
+
|
||||
+ device_tree_module.get_actions()
|
||||
+ self.assertIsNotNone(self.module._storage_playground)
|
||||
+
|
||||
@patch_dbus_publish_object
|
||||
def get_device_tree_test(self, publisher):
|
||||
"""Test GetDeviceTree."""
|
||||
diff --git a/tests/nosetests/pyanaconda_tests/util_test.py b/tests/nosetests/pyanaconda_tests/util_test.py
|
||||
index 1da8362dc..76f1c4465 100644
|
||||
--- a/tests/nosetests/pyanaconda_tests/util_test.py
|
||||
+++ b/tests/nosetests/pyanaconda_tests/util_test.py
|
||||
@@ -29,7 +29,7 @@ from unittest.mock import Mock, patch
|
||||
from pyanaconda.errors import ExitError
|
||||
from pyanaconda.core.process_watchers import WatchProcesses
|
||||
from pyanaconda.core import util
|
||||
-from pyanaconda.core.util import synchronized
|
||||
+from pyanaconda.core.util import synchronized, LazyObject
|
||||
from pyanaconda.core.configuration.anaconda import conf
|
||||
|
||||
from timer import timer
|
||||
@@ -829,3 +829,98 @@ class MiscTests(unittest.TestCase):
|
||||
)
|
||||
self.assertEqual(get_anaconda_version_string(), "1.0")
|
||||
self.assertEqual(get_anaconda_version_string(build_time_version=True), "1.0-1")
|
||||
+
|
||||
+
|
||||
+class LazyObjectTestCase(unittest.TestCase):
|
||||
+
|
||||
+ class Object(object):
|
||||
+
|
||||
+ def __init__(self):
|
||||
+ self._x = 0
|
||||
+
|
||||
+ @property
|
||||
+ def x(self):
|
||||
+ return self._x
|
||||
+
|
||||
+ @x.setter
|
||||
+ def x(self, value):
|
||||
+ self._x = value
|
||||
+
|
||||
+ def f(self, value):
|
||||
+ self._x += value
|
||||
+
|
||||
+ def setUp(self):
|
||||
+ self._obj = None
|
||||
+
|
||||
+ @property
|
||||
+ def obj(self):
|
||||
+ if not self._obj:
|
||||
+ self._obj = self.Object()
|
||||
+
|
||||
+ return self._obj
|
||||
+
|
||||
+ @property
|
||||
+ def lazy_obj(self):
|
||||
+ return LazyObject(lambda: self.obj)
|
||||
+
|
||||
+ def get_set_test(self):
|
||||
+ self.assertIsNotNone(self.lazy_obj)
|
||||
+ self.assertIsNone(self._obj)
|
||||
+
|
||||
+ self.assertEqual(self.lazy_obj.x, 0)
|
||||
+ self.assertIsNotNone(self._obj)
|
||||
+
|
||||
+ self.obj.x = -10
|
||||
+ self.assertEqual(self.obj.x, -10)
|
||||
+ self.assertEqual(self.lazy_obj.x, -10)
|
||||
+
|
||||
+ self.lazy_obj.x = 10
|
||||
+ self.assertEqual(self.obj.x, 10)
|
||||
+ self.assertEqual(self.lazy_obj.x, 10)
|
||||
+
|
||||
+ self.lazy_obj.f(90)
|
||||
+ self.assertEqual(self.obj.x, 100)
|
||||
+ self.assertEqual(self.lazy_obj.x, 100)
|
||||
+
|
||||
+ def eq_test(self):
|
||||
+ a = object()
|
||||
+ lazy_a1 = LazyObject(lambda: a)
|
||||
+ lazy_a2 = LazyObject(lambda: a)
|
||||
+
|
||||
+ self.assertEqual(a, lazy_a1)
|
||||
+ self.assertEqual(lazy_a1, a)
|
||||
+
|
||||
+ self.assertEqual(a, lazy_a2)
|
||||
+ self.assertEqual(lazy_a2, a)
|
||||
+
|
||||
+ self.assertEqual(lazy_a1, lazy_a2)
|
||||
+ self.assertEqual(lazy_a2, lazy_a1)
|
||||
+
|
||||
+ self.assertEqual(lazy_a1, lazy_a1)
|
||||
+ self.assertEqual(lazy_a2, lazy_a2)
|
||||
+
|
||||
+ def neq_test(self):
|
||||
+ a = object()
|
||||
+ lazy_a = LazyObject(lambda: a)
|
||||
+
|
||||
+ b = object()
|
||||
+ lazy_b = LazyObject(lambda: b)
|
||||
+
|
||||
+ self.assertNotEqual(b, lazy_a)
|
||||
+ self.assertNotEqual(lazy_a, b)
|
||||
+
|
||||
+ self.assertNotEqual(lazy_a, lazy_b)
|
||||
+ self.assertNotEqual(lazy_b, lazy_a)
|
||||
+
|
||||
+ def hash_test(self):
|
||||
+ a = object()
|
||||
+ lazy_a1 = LazyObject(lambda: a)
|
||||
+ lazy_a2 = LazyObject(lambda: a)
|
||||
+
|
||||
+ b = object()
|
||||
+ lazy_b1 = LazyObject(lambda: b)
|
||||
+ lazy_b2 = LazyObject(lambda: b)
|
||||
+
|
||||
+ self.assertEqual({a, lazy_a1, lazy_a2}, {a})
|
||||
+ self.assertEqual({b, lazy_b1, lazy_b2}, {b})
|
||||
+ self.assertEqual({lazy_a1, lazy_b2}, {a, b})
|
||||
@ -1,32 +0,0 @@
|
||||
From ac6010448ba29f8c5b979d11cabeb09a91cf260c Mon Sep 17 00:00:00 2001
|
||||
From: Mikhail Novosyolov <m.novosyolov@rosalinux.ru>
|
||||
Date: Mon, 31 Aug 2020 23:44:17 +0300
|
||||
Subject: [PATCH] Recognize systemd.unit=anaconda.target in anaconda-generator
|
||||
|
||||
anaconda.target may be activated not only by symlinking /etc/systemd/systemd/default.target,
|
||||
this symlink may even not exist, but by e.g. adding "systemd.unit=anaconda.target"
|
||||
to kernel cmdline (see kernel-command-line(7) from systemd)
|
||||
|
||||
`systemctl is-active -q anaconda.target` could be used here, but systemctl is not available from systemd generators.
|
||||
|
||||
P.S. See https://www.redhat.com/archives/anaconda-devel-list/2012-August/msg00118.html for description why generator is needed.
|
||||
---
|
||||
data/systemd/anaconda-generator | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/data/systemd/anaconda-generator b/data/systemd/anaconda-generator
|
||||
index cda87480d..bafe74ea1 100755
|
||||
--- a/data/systemd/anaconda-generator
|
||||
+++ b/data/systemd/anaconda-generator
|
||||
@@ -5,7 +5,7 @@
|
||||
ANACONDA_TARGET="/lib/systemd/system/anaconda.target"
|
||||
CURRENT_DEFAULT_TARGET=$(readlink /etc/systemd/system/default.target)
|
||||
|
||||
-if [ "$ANACONDA_TARGET" != "$CURRENT_DEFAULT_TARGET" ]; then
|
||||
+if ! { [ "$ANACONDA_TARGET" = "$CURRENT_DEFAULT_TARGET" ] || grep -q 'systemd.unit=anaconda.target' /proc/cmdline ;} ; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
From 2acb1357ee8b931662a1353a8956d5a0be176dec Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Slavik <vslavik@redhat.com>
|
||||
Date: Tue, 23 Jun 2020 18:52:32 +0200
|
||||
Subject: [PATCH] Reconfigure DNF payload after options are set
|
||||
|
||||
Fixes broken multilib boot option.
|
||||
|
||||
Resolves: rhbz#1847603
|
||||
---
|
||||
pyanaconda/payload/dnf/payload.py | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/pyanaconda/payload/dnf/payload.py b/pyanaconda/payload/dnf/payload.py
|
||||
index f92720890..b38e78cd3 100644
|
||||
--- a/pyanaconda/payload/dnf/payload.py
|
||||
+++ b/pyanaconda/payload/dnf/payload.py
|
||||
@@ -173,6 +173,9 @@ class DNFPayload(Payload):
|
||||
if opts.multiLib:
|
||||
self.data.packages.multiLib = opts.multiLib
|
||||
|
||||
+ # Reset all the other things now that we have new configuration.
|
||||
+ self._configure()
|
||||
+
|
||||
@property
|
||||
def type(self):
|
||||
"""The DBus type of the payload."""
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,120 +0,0 @@
|
||||
From 6f27de8a38cc7900bb35a4fac4ec258f50207468 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Thu, 23 Jul 2020 13:49:41 +0200
|
||||
Subject: [PATCH] Reload treeinfo repositories on every payload reset
|
||||
|
||||
Remove old repositories before loading new ones. We are changing the logic to
|
||||
load new ones every time the base repo is changed.
|
||||
|
||||
This will solve problem that additional repositories pointing to an
|
||||
invalid path. This is happening because we moved source mounting to a
|
||||
different folders for each source.
|
||||
|
||||
Resolves: rhbz#1851207
|
||||
(cherry picked from commit 7b9e6c8ac29d56ed8b5d657ed6729cb5e239d09c)
|
||||
---
|
||||
pyanaconda/payload/base.py | 8 +-------
|
||||
pyanaconda/payload/dnf/payload.py | 29 +++++++++++++++++++----------
|
||||
2 files changed, 20 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/payload/base.py b/pyanaconda/payload/base.py
|
||||
index 285e27e05..5e56dbb29 100644
|
||||
--- a/pyanaconda/payload/base.py
|
||||
+++ b/pyanaconda/payload/base.py
|
||||
@@ -39,8 +39,6 @@ class Payload(metaclass=ABCMeta):
|
||||
"""
|
||||
self.data = data
|
||||
|
||||
- self._first_payload_reset = True
|
||||
-
|
||||
# A list of verbose error strings from the subclass
|
||||
self.verbose_errors = []
|
||||
|
||||
@@ -67,10 +65,6 @@ class Payload(metaclass=ABCMeta):
|
||||
"""The DBus type of the source."""
|
||||
return None
|
||||
|
||||
- @property
|
||||
- def first_payload_reset(self):
|
||||
- return self._first_payload_reset
|
||||
-
|
||||
def is_ready(self):
|
||||
"""Is the payload ready?"""
|
||||
return True
|
||||
@@ -89,7 +83,7 @@ class Payload(metaclass=ABCMeta):
|
||||
|
||||
This method could be overriden.
|
||||
"""
|
||||
- self._first_payload_reset = False
|
||||
+ pass
|
||||
|
||||
def release(self):
|
||||
"""Release any resources in use by this object, but do not do final
|
||||
diff --git a/pyanaconda/payload/dnf/payload.py b/pyanaconda/payload/dnf/payload.py
|
||||
index b693c776d..227d32c82 100644
|
||||
--- a/pyanaconda/payload/dnf/payload.py
|
||||
+++ b/pyanaconda/payload/dnf/payload.py
|
||||
@@ -1455,6 +1455,8 @@ class DNFPayload(Payload):
|
||||
log.info("Configuring the base repo")
|
||||
self.reset()
|
||||
|
||||
+ self._cleanup_old_treeinfo_repositories()
|
||||
+
|
||||
# Find the source and its type.
|
||||
source_proxy = self.get_source_proxy()
|
||||
source_type = source_proxy.Type
|
||||
@@ -1507,11 +1509,9 @@ class DNFPayload(Payload):
|
||||
self._refresh_install_tree(data)
|
||||
self._base.conf.releasever = self._get_release_version(install_tree_url)
|
||||
base_repo_url = self._get_base_repo_location(install_tree_url)
|
||||
-
|
||||
- if self.first_payload_reset:
|
||||
- self._add_treeinfo_repositories(install_tree_url, base_repo_url)
|
||||
-
|
||||
log.debug("releasever from %s is %s", base_repo_url, self._base.conf.releasever)
|
||||
+
|
||||
+ self._load_treeinfo_repositories(base_repo_url)
|
||||
except configparser.MissingSectionHeaderError as e:
|
||||
log.error("couldn't set releasever from base repo (%s): %s", source_type, e)
|
||||
|
||||
@@ -1817,12 +1817,11 @@ class DNFPayload(Payload):
|
||||
log.debug("No base repository found in treeinfo file. Using installation tree root.")
|
||||
return install_tree_url
|
||||
|
||||
- def _add_treeinfo_repositories(self, install_tree_url, base_repo_url=None):
|
||||
- """Add all repositories from treeinfo file which are not already loaded.
|
||||
+ def _load_treeinfo_repositories(self, base_repo_url):
|
||||
+ """Load new repositories from treeinfo file.
|
||||
|
||||
- :param install_tree_url: Url to the installation tree root.
|
||||
- :param base_repo_url: Base repository url. This is not saved anywhere when the function
|
||||
- is called. It will be add to the existing urls if not None.
|
||||
+ :param base_repo_url: base repository url. This is not saved anywhere when the function
|
||||
+ is called. It will be add to the existing urls if not None.
|
||||
"""
|
||||
if self._install_tree_metadata:
|
||||
existing_urls = []
|
||||
@@ -1843,9 +1842,19 @@ class DNFPayload(Payload):
|
||||
repo = RepoData(name=repo_md.name, baseurl=repo_md.path,
|
||||
install=False, enabled=repo_enabled)
|
||||
repo.treeinfo_origin = True
|
||||
+ log.debug("Adding new treeinfo repository %s", repo_md.name)
|
||||
self.add_repo(repo)
|
||||
|
||||
- return install_tree_url
|
||||
+ def _cleanup_old_treeinfo_repositories(self):
|
||||
+ """Remove all old treeinfo repositories before loading new ones.
|
||||
+
|
||||
+ Find all repositories added from treeinfo file and remove them. After this step new
|
||||
+ repositories will be loaded from the new link.
|
||||
+ """
|
||||
+ for ks_repo_name in self.addons:
|
||||
+ if self.get_addon_repo(ks_repo_name).treeinfo_origin:
|
||||
+ log.debug("Removing old treeinfo repository %s", ks_repo_name)
|
||||
+ self.remove_repo(ks_repo_name)
|
||||
|
||||
def _write_dnf_repo(self, repo, repo_path):
|
||||
"""Write a repo object to a DNF repo.conf file.
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,128 +0,0 @@
|
||||
From 6f52b733470d5565bc8e9a2a2415997d0ecbba54 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Mon, 27 Jul 2020 18:08:30 +0200
|
||||
Subject: [PATCH] Remove treeinfo repositories instead of disabling
|
||||
|
||||
We now remove repositories from treeinfo file on each payload reset. In that
|
||||
case we should not disable these in the source spoke but instead remove them.
|
||||
|
||||
We should ideally also show them back to user when the source is switched back
|
||||
but that logic to detect if base repo repository have changed is not trivial and
|
||||
we had to change _update_payload_repos to achieve this. We don't want to
|
||||
introduce any more regressions and that code change could do that.
|
||||
|
||||
Related: rhbz#1851207
|
||||
(cherry picked from commit 8b99a20860a193d2816b53e89e562ba01bb1a825)
|
||||
---
|
||||
.../ui/gui/spokes/installation_source.py | 44 ++++++++++++-------
|
||||
1 file changed, 28 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/installation_source.py b/pyanaconda/ui/gui/spokes/installation_source.py
|
||||
index 5b2f56b80..0bd3b6938 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/installation_source.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/installation_source.py
|
||||
@@ -429,8 +429,6 @@ class SourceSpoke(NormalSpoke, GUISpokeInputCheckHandler, SourceSwitchHandler):
|
||||
self._network_module = NETWORK.get_proxy()
|
||||
self._device_tree = STORAGE.get_proxy(DEVICE_TREE)
|
||||
|
||||
- self._treeinfo_repos_already_disabled = False
|
||||
-
|
||||
def apply(self):
|
||||
source_changed = self._update_payload_source()
|
||||
repo_changed = self._update_payload_repos()
|
||||
@@ -1205,7 +1203,7 @@ class SourceSpoke(NormalSpoke, GUISpokeInputCheckHandler, SourceSwitchHandler):
|
||||
# the newly enabled button as well as the previously enabled (now
|
||||
# disabled) button.
|
||||
self._on_source_toggled(button, relatedBox)
|
||||
- self._disable_treeinfo_repositories()
|
||||
+ self._remove_treeinfo_repositories()
|
||||
|
||||
def _on_source_toggled(self, button, relatedBox):
|
||||
enabled = button.get_active()
|
||||
@@ -1283,7 +1281,7 @@ class SourceSpoke(NormalSpoke, GUISpokeInputCheckHandler, SourceSwitchHandler):
|
||||
button.set_label(os.path.basename(iso_file))
|
||||
button.set_use_underline(False)
|
||||
self._verify_iso_button.set_sensitive(True)
|
||||
- self._disable_treeinfo_repositories()
|
||||
+ self._remove_treeinfo_repositories()
|
||||
|
||||
def on_proxy_clicked(self, button):
|
||||
dialog = ProxyDialog(self.data, self._proxy_url)
|
||||
@@ -1331,7 +1329,7 @@ class SourceSpoke(NormalSpoke, GUISpokeInputCheckHandler, SourceSwitchHandler):
|
||||
|
||||
def on_protocol_changed(self, combo):
|
||||
self._on_protocol_changed()
|
||||
- self._disable_treeinfo_repositories()
|
||||
+ self._remove_treeinfo_repositories()
|
||||
|
||||
def _on_protocol_changed(self):
|
||||
# Only allow the URL entry to be used if we're using an HTTP/FTP
|
||||
@@ -1431,8 +1429,6 @@ class SourceSpoke(NormalSpoke, GUISpokeInputCheckHandler, SourceSwitchHandler):
|
||||
self._clear_repo_info()
|
||||
self._repo_entry_box.set_sensitive(False)
|
||||
|
||||
- self._treeinfo_repos_already_disabled = False
|
||||
-
|
||||
def _unique_repo_name(self, name):
|
||||
""" Return a unique variation of the name if it already
|
||||
exists in the repo store.
|
||||
@@ -1491,13 +1487,16 @@ class SourceSpoke(NormalSpoke, GUISpokeInputCheckHandler, SourceSwitchHandler):
|
||||
self._repo_store[repo_model_path][REPO_ENABLED_COL] = enabled
|
||||
self._repo_store[repo_model_path][REPO_OBJ].enabled = enabled
|
||||
|
||||
- def _disable_treeinfo_repositories(self):
|
||||
+ def _remove_treeinfo_repositories(self):
|
||||
"""Disable all repositories loaded from the .treeinfo file"""
|
||||
- if not self._treeinfo_repos_already_disabled:
|
||||
- self._treeinfo_repos_already_disabled = True
|
||||
- for repo_item in self._repo_store:
|
||||
- if repo_item[REPO_OBJ].treeinfo_origin:
|
||||
- self._set_repo_enabled(repo_item.path, False)
|
||||
+ removal_repo_list = []
|
||||
+
|
||||
+ for repo_item in self._repo_store:
|
||||
+ if repo_item[REPO_OBJ].treeinfo_origin:
|
||||
+ removal_repo_list.append(repo_item.path)
|
||||
+
|
||||
+ for path in removal_repo_list:
|
||||
+ self._remove_repository(path)
|
||||
|
||||
def _clear_repo_info(self):
|
||||
""" Clear the text from the repo entry fields
|
||||
@@ -1589,7 +1588,7 @@ class SourceSpoke(NormalSpoke, GUISpokeInputCheckHandler, SourceSwitchHandler):
|
||||
def on_urlEntry_changed(self, editable, data=None):
|
||||
# Check for and remove a URL prefix that matches the protocol dropdown
|
||||
self._on_urlEtry_changed(editable)
|
||||
- self._disable_treeinfo_repositories()
|
||||
+ self._remove_treeinfo_repositories()
|
||||
|
||||
def _on_urlEtry_changed(self, editable):
|
||||
self._remove_url_prefix(editable, self._protocol_combo_box, self.on_urlEntry_changed)
|
||||
@@ -1619,9 +1618,22 @@ class SourceSpoke(NormalSpoke, GUISpokeInputCheckHandler, SourceSwitchHandler):
|
||||
self._repo_entry_box.set_sensitive(True)
|
||||
|
||||
def on_removeRepo_clicked(self, button):
|
||||
- """ Remove the selected repository
|
||||
+ """Remove the selected repository"""
|
||||
+ self._remove_repository()
|
||||
+
|
||||
+ def _remove_repository(self, repo_model_path=None):
|
||||
+ """Remove repository on repo_model_path or current selection.
|
||||
+
|
||||
+ If repo_model_path is not specified then current selection will be used.
|
||||
+
|
||||
+ :param repo_model_path: repo_model_path of what we can remove or None
|
||||
+ :type repo_model_path: repo_store repo_model_path
|
||||
"""
|
||||
- itr = self._repo_selection.get_selected()[1]
|
||||
+ if repo_model_path is None:
|
||||
+ itr = self._repo_store[repo_model_path].iter
|
||||
+ else:
|
||||
+ itr = self._repo_selection.get_selected()[1]
|
||||
+
|
||||
if not itr:
|
||||
return
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
From d76c6060ea59215dbb90299b28fc8d59abf8e0fa Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Wed, 13 May 2020 18:59:26 +0200
|
||||
Subject: [PATCH] Reset the RAID level of the device request (#1828092)
|
||||
|
||||
In the custom partitioning spoke, always reset the RAID level of the
|
||||
device request when the device type changes. Otherwise, the new type
|
||||
doesn't have to support the old RAID level.
|
||||
|
||||
Resolves: rhbz#1828092
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/custom_storage.py | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/custom_storage.py b/pyanaconda/ui/gui/spokes/custom_storage.py
|
||||
index 4e174a5f5..f0596263b 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/custom_storage.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/custom_storage.py
|
||||
@@ -1729,7 +1729,8 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
# this has to be done before calling populate_raid since it will need
|
||||
# the raid level combo to contain the relevant raid levels for the new
|
||||
# device type
|
||||
- self._populate_raid()
|
||||
+ self._request.device_raid_level = get_default_raid_level(new_type)
|
||||
+ self._populate_raid(self._request.device_raid_level)
|
||||
|
||||
# Generate a new container configuration for the new type.
|
||||
self._request = DeviceFactoryRequest.from_structure(
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,134 +0,0 @@
|
||||
From 8032e0a9eae5093e1246af4d3906ad65d5aade12 Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Wed, 12 Aug 2020 12:38:27 +0200
|
||||
Subject: [PATCH] Reset the state of the custom partitioning spoke
|
||||
|
||||
We should reset the state of the custom partitioning spoke after every user
|
||||
interaction. If we don't reset the _back_already_clicked attribute, the final
|
||||
check of the storage configuration might be skipped and the status of the
|
||||
storage spoke might show an error from the previously failed check.
|
||||
|
||||
(cherry picked from commit 0aa3abfb6fb137746a393588ff9315807a65f7b9)
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/custom_storage.py | 28 +++++++++++-----------
|
||||
1 file changed, 14 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/custom_storage.py b/pyanaconda/ui/gui/spokes/custom_storage.py
|
||||
index a5e568f..6c9f6f6 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/custom_storage.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/custom_storage.py
|
||||
@@ -280,7 +280,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
self._storage_module.ResetPartitioning()
|
||||
|
||||
def refresh(self):
|
||||
- self.clear_errors()
|
||||
+ self.reset_state()
|
||||
NormalSpoke.refresh(self)
|
||||
|
||||
# Make sure the storage spoke execute method has finished before we
|
||||
@@ -294,8 +294,6 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
self._partitioning = create_partitioning(PARTITIONING_METHOD_INTERACTIVE)
|
||||
self._device_tree = STORAGE.get_proxy(self._partitioning.GetDeviceTree())
|
||||
|
||||
- self._back_already_clicked = False
|
||||
-
|
||||
# Get the name of the new installation.
|
||||
self._os_name = self._device_tree.GenerateSystemName()
|
||||
|
||||
@@ -554,8 +552,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
# just-removed device
|
||||
return
|
||||
|
||||
- self.clear_errors()
|
||||
- self._back_already_clicked = False
|
||||
+ self.reset_state()
|
||||
|
||||
log.debug("Saving the right side for device: %s", device_name)
|
||||
|
||||
@@ -979,7 +976,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
|
||||
def on_add_clicked(self, button):
|
||||
# Clear any existing errors
|
||||
- self.clear_errors()
|
||||
+ self.reset_state()
|
||||
|
||||
# Save anything from the currently displayed mount point.
|
||||
self._save_right_side(self._accordion.current_selector)
|
||||
@@ -996,8 +993,6 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
dialog.window.destroy()
|
||||
return
|
||||
|
||||
- self._back_already_clicked = False
|
||||
-
|
||||
# Gather data about the added mount point.
|
||||
request = DeviceFactoryRequest()
|
||||
request.mount_point = dialog.mount_point
|
||||
@@ -1006,7 +1001,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
request.disks = self._selected_disks
|
||||
|
||||
# Clear errors and try to add the mountpoint/device.
|
||||
- self.clear_errors()
|
||||
+ self.reset_state()
|
||||
|
||||
try:
|
||||
self._device_tree.AddDevice(
|
||||
@@ -1065,7 +1060,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
return
|
||||
|
||||
# Remove selected items.
|
||||
- self.clear_errors()
|
||||
+ self.reset_state()
|
||||
|
||||
try:
|
||||
self._remove_selected_devices()
|
||||
@@ -1187,7 +1182,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
# disk set management happens through container edit on RHS
|
||||
return
|
||||
|
||||
- self.clear_errors()
|
||||
+ self.reset_state()
|
||||
|
||||
dialog = DisksDialog(
|
||||
self.data,
|
||||
@@ -1448,7 +1443,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
|
||||
Note: There are never any non-existent devices around when this runs.
|
||||
"""
|
||||
- self.clear_errors()
|
||||
+ self.reset_state()
|
||||
|
||||
# Create the partitioning request.
|
||||
request = PartitioningRequest()
|
||||
@@ -1762,6 +1757,10 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
self._error = None
|
||||
self.clear_info()
|
||||
|
||||
+ def reset_state(self):
|
||||
+ self.clear_errors()
|
||||
+ self._back_already_clicked = False
|
||||
+
|
||||
# This callback is for the button that just resets the UI to anaconda's
|
||||
# current understanding of the disk layout.
|
||||
def on_reset_clicked(self, *args):
|
||||
@@ -1846,7 +1845,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
return
|
||||
|
||||
# Clear any existing errors
|
||||
- self.clear_errors()
|
||||
+ self.reset_state()
|
||||
|
||||
# Save anything from the currently displayed mount point.
|
||||
self._save_right_side(selector)
|
||||
@@ -1861,7 +1860,8 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
if not selector:
|
||||
return
|
||||
|
||||
- self.clear_errors()
|
||||
+ self.reset_state()
|
||||
+
|
||||
device_name = selector.device_name
|
||||
passphrase = self._passphraseEntry.get_text()
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
From 1f05aab7135ee3c5843c24a2a89bb707dcbe0dc5 Mon Sep 17 00:00:00 2001
|
||||
From: Radek Vykydal <rvykydal@redhat.com>
|
||||
Date: Thu, 17 Sep 2020 07:49:54 +0200
|
||||
Subject: [PATCH] Root password is mandatory if there is *not* admin user.
|
||||
|
||||
Related: rhbz#1876727
|
||||
---
|
||||
pyanaconda/ui/tui/spokes/root_password.py | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/tui/spokes/root_password.py b/pyanaconda/ui/tui/spokes/root_password.py
|
||||
index 6ebc8f65e..345b5dcfe 100644
|
||||
--- a/pyanaconda/ui/tui/spokes/root_password.py
|
||||
+++ b/pyanaconda/ui/tui/spokes/root_password.py
|
||||
@@ -61,8 +61,8 @@ class PasswordSpoke(FirstbootSpokeMixIn, NormalTUISpoke):
|
||||
|
||||
@property
|
||||
def mandatory(self):
|
||||
- """Root password spoke is mandatory if no users with admin rights have been requested."""
|
||||
- return self._users_module.CheckAdminUserExists()
|
||||
+ """Only mandatory if no admin user has been requested."""
|
||||
+ return not self._users_module.CheckAdminUserExists()
|
||||
|
||||
@property
|
||||
def status(self):
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,86 +0,0 @@
|
||||
From 2ca64adb8effcdfa8a883ee9f8fc2015cbece685 Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Tue, 28 Jul 2020 11:58:23 +0200
|
||||
Subject: [PATCH] Run actions of the Resize dialog in the reversed order
|
||||
(#1856496)
|
||||
|
||||
If there is a disk with two logical partitions sda5 and sda6 and we remove sda5,
|
||||
Blivet renames the partition sda6 to sda5, so the actions for sda6 are no longer
|
||||
valid. Run actions in the reversed order to avoid this situation.
|
||||
|
||||
Resolves: rhbz#1856496
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/lib/resize.py | 29 +++++++++++++++++++++-----
|
||||
1 file changed, 24 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/lib/resize.py b/pyanaconda/ui/gui/spokes/lib/resize.py
|
||||
index 71dcffb05..4695e5332 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/lib/resize.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/lib/resize.py
|
||||
@@ -19,6 +19,7 @@
|
||||
from collections import namedtuple
|
||||
from blivet.size import Size
|
||||
|
||||
+from pyanaconda.anaconda_loggers import get_module_logger
|
||||
from pyanaconda.core.i18n import _, C_, N_, P_
|
||||
from pyanaconda.modules.common.constants.services import STORAGE
|
||||
from pyanaconda.modules.common.structures.storage import OSData, DeviceData, DeviceFormatData
|
||||
@@ -55,6 +56,8 @@ SHRINK = N_("Shrink")
|
||||
DELETE = N_("Delete")
|
||||
NOTHING = ""
|
||||
|
||||
+log = get_module_logger(__name__)
|
||||
+
|
||||
|
||||
class ResizeDialog(GUIObject):
|
||||
builderObjects = ["actionStore", "diskStore", "resizeDialog", "resizeAdjustment"]
|
||||
@@ -521,7 +524,8 @@ class ResizeDialog(GUIObject):
|
||||
self._update_reclaim_button(self._selected_reclaimable_space)
|
||||
self._update_action_buttons()
|
||||
|
||||
- def _schedule_actions(self, model, path, itr, *args):
|
||||
+ def _collect_actionable_rows(self, model, path, itr, rows):
|
||||
+ """Collect rows that can be transformed into actions."""
|
||||
obj = PartStoreRow(*model[itr])
|
||||
|
||||
if not obj.name:
|
||||
@@ -530,17 +534,32 @@ class ResizeDialog(GUIObject):
|
||||
if not obj.editable:
|
||||
return False
|
||||
|
||||
+ rows.append(obj)
|
||||
+ return False
|
||||
+
|
||||
+ def _schedule_actions(self, obj):
|
||||
+ """Schedule actions for the given row object."""
|
||||
if obj.action == _(PRESERVE):
|
||||
- pass
|
||||
+ log.debug("Preserve %s.", obj.name)
|
||||
elif obj.action == _(SHRINK):
|
||||
+ log.debug("Shrink %s to %s.", obj.name, Size(obj.target))
|
||||
self._device_tree.ShrinkDevice(obj.name, obj.target)
|
||||
elif obj.action == _(DELETE):
|
||||
+ log.debug("Remove %s.", obj.name)
|
||||
self._device_tree.RemoveDevice(obj.name)
|
||||
|
||||
- return False
|
||||
-
|
||||
def on_resize_clicked(self, *args):
|
||||
- self._disk_store.foreach(self._schedule_actions, None)
|
||||
+ rows = []
|
||||
+
|
||||
+ # Collect the rows.
|
||||
+ self._disk_store.foreach(self._collect_actionable_rows, rows)
|
||||
+
|
||||
+ # Process rows in the reversed order. If there is a disk with
|
||||
+ # two logical partitions sda5 and sda6 and we remove sda5, Blivet
|
||||
+ # renames the partition sda6 to sda5, so the actions for sda6 are
|
||||
+ # no longer valid. See the bug 1856496.
|
||||
+ for obj in reversed(rows):
|
||||
+ self._schedule_actions(obj)
|
||||
|
||||
def on_delete_all_clicked(self, button, *args):
|
||||
if button.get_label() == C_("GUI|Reclaim Dialog", "Delete _all"):
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,59 +0,0 @@
|
||||
From 65b176260404087f625132697c1e299db0b0163e Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Wed, 8 Jul 2020 19:07:54 +0200
|
||||
Subject: [PATCH] Schedule timed actions with the right selector (#1851647)
|
||||
|
||||
The timed actions of the Custom Partitioning spoke should be scheduled with
|
||||
the specified selector. Otherwise, the action will use the current selector
|
||||
that might be different.
|
||||
|
||||
Resolves: rhbz#1851647
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/custom_storage.py | 20 ++++++++++++++++----
|
||||
1 file changed, 16 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/custom_storage.py b/pyanaconda/ui/gui/spokes/custom_storage.py
|
||||
index b89866c..a5e568f 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/custom_storage.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/custom_storage.py
|
||||
@@ -1836,21 +1836,33 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
dlg.run()
|
||||
dlg.destroy()
|
||||
|
||||
- @timed_action(delay=50, threshold=100)
|
||||
def on_update_settings_clicked(self, button):
|
||||
+ self._update_settings(self._accordion.current_selector)
|
||||
+
|
||||
+ @timed_action(delay=50, threshold=100)
|
||||
+ def _update_settings(self, selector):
|
||||
""" call _save_right_side, then, perhaps, populate_right_side. """
|
||||
+ if not selector:
|
||||
+ return
|
||||
+
|
||||
# Clear any existing errors
|
||||
self.clear_errors()
|
||||
|
||||
# Save anything from the currently displayed mount point.
|
||||
- self._save_right_side(self._accordion.current_selector)
|
||||
+ self._save_right_side(selector)
|
||||
self._applyButton.set_sensitive(False)
|
||||
|
||||
- @timed_action(delay=50, threshold=100)
|
||||
def on_unlock_clicked(self, *args):
|
||||
+ self._unlock_device(self._accordion.current_selector)
|
||||
+
|
||||
+ @timed_action(delay=50, threshold=100)
|
||||
+ def _unlock_device(self, selector):
|
||||
""" try to open the luks device, populate, then call _do_refresh. """
|
||||
+ if not selector:
|
||||
+ return
|
||||
+
|
||||
self.clear_errors()
|
||||
- device_name = self._accordion.current_selector.device_name
|
||||
+ device_name = selector.device_name
|
||||
passphrase = self._passphraseEntry.get_text()
|
||||
|
||||
log.info("Trying to unlock device %s.", device_name)
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,96 +0,0 @@
|
||||
From 4bf4ba6d9a11cfd652ce48cdaea86bd617b6332a Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Slavik <vslavik@redhat.com>
|
||||
Date: Tue, 28 Apr 2020 14:40:53 +0200
|
||||
Subject: [PATCH] Show warning message when entered size is not valid
|
||||
|
||||
Requires also reordering checks such that the identical text test comes later.
|
||||
|
||||
Resolves: rhbz#1809573
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/custom_storage.py | 31 ++++++++++++++-----
|
||||
.../gui/spokes/lib/custom_storage_helpers.py | 10 ++++++
|
||||
2 files changed, 33 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/custom_storage.py b/pyanaconda/ui/gui/spokes/custom_storage.py
|
||||
index 08e62cc40..f3755c48c 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/custom_storage.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/custom_storage.py
|
||||
@@ -63,7 +63,8 @@ from pyanaconda.ui.gui.spokes.lib.custom_storage_helpers import get_size_from_en
|
||||
get_selected_raid_level, get_default_raid_level, get_container_type, AddDialog,\
|
||||
ConfirmDeleteDialog, DisksDialog, ContainerDialog, NOTEBOOK_LABEL_PAGE, NOTEBOOK_DETAILS_PAGE,\
|
||||
NOTEBOOK_LUKS_PAGE, NOTEBOOK_UNEDITABLE_PAGE, NOTEBOOK_INCOMPLETE_PAGE, NEW_CONTAINER_TEXT,\
|
||||
- CONTAINER_TOOLTIP, get_supported_device_raid_levels, generate_request_description
|
||||
+ CONTAINER_TOOLTIP, DESIRED_CAPACITY_ERROR, get_supported_device_raid_levels, \
|
||||
+ generate_request_description
|
||||
from pyanaconda.ui.gui.spokes.lib.passphrase import PassphraseDialog
|
||||
from pyanaconda.ui.gui.spokes.lib.refresh import RefreshDialog
|
||||
from pyanaconda.ui.gui.spokes.lib.summary import ActionSummaryDialog
|
||||
@@ -1552,23 +1553,37 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
self._request.device_raid_level = get_selected_raid_level(self._raidLevelCombo)
|
||||
self.on_value_changed()
|
||||
|
||||
- def on_size_changed(self, widget):
|
||||
+ @timed_action(750, 1500, False)
|
||||
+ def on_size_changed(self, *args):
|
||||
+ """Callback for text change in "desired capacity" widget"""
|
||||
if not self._sizeEntry.get_sensitive():
|
||||
return
|
||||
|
||||
- current_size = Size(self._request.device_size)
|
||||
- displayed_size = current_size.human_readable(max_places=self.MAX_SIZE_PLACES)
|
||||
-
|
||||
- if displayed_size == self._sizeEntry.get_text():
|
||||
- return
|
||||
-
|
||||
size = get_size_from_entry(
|
||||
self._sizeEntry,
|
||||
lower_bound=self.MIN_SIZE_ENTRY,
|
||||
units=SIZE_UNITS_DEFAULT
|
||||
)
|
||||
|
||||
+ # Show warning if the size string is invalid. Field self._error is used as a "flag" that
|
||||
+ # the last error was the same. This is done because this warning can fire on every change,
|
||||
+ # so it would keep flickering at the bottom as you type.
|
||||
if size is None:
|
||||
+ if self._error != DESIRED_CAPACITY_ERROR:
|
||||
+ self.clear_errors()
|
||||
+ self.set_detailed_warning(
|
||||
+ _("Invalid input. Specify the Desired Capacity in whole or decimal numbers, "
|
||||
+ "with an appropriate unit."),
|
||||
+ _(DESIRED_CAPACITY_ERROR)
|
||||
+ )
|
||||
+ return
|
||||
+ elif self._error == DESIRED_CAPACITY_ERROR:
|
||||
+ self.clear_errors()
|
||||
+
|
||||
+ current_size = Size(self._request.device_size)
|
||||
+ displayed_size = current_size.human_readable(max_places=self.MAX_SIZE_PLACES)
|
||||
+
|
||||
+ if displayed_size == self._sizeEntry.get_text():
|
||||
return
|
||||
|
||||
self._request.device_size = size.get_bytes()
|
||||
diff --git a/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py b/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py
|
||||
index f7ae6cfa3..0dffaf0f7 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py
|
||||
@@ -49,6 +49,16 @@ CONTAINER_TOOLTIP = N_("Create or select %(container_type)s")
|
||||
CONTAINER_DIALOG_TITLE = N_("CONFIGURE %(container_type)s")
|
||||
CONTAINER_DIALOG_TEXT = N_("Please create a name for this %(container_type)s "
|
||||
"and select at least one disk below.")
|
||||
+DESIRED_CAPACITY_ERROR = N_(
|
||||
+ "Specify the Desired Capacity in whole or decimal numbers, with an appropriate unit.\n\n"
|
||||
+ "Spaces separating digit groups are not allowed. Units consist of a decimal or binary "
|
||||
+ "prefix, and optionally the letter B. Letter case does not matter for units. The default "
|
||||
+ "unit used when units are left out is MiB.\n\n"
|
||||
+ "Examples of valid input:\n"
|
||||
+ "'100 GiB' = 100 gibibytes\n"
|
||||
+ "'512m' = 512 megabytes\n"
|
||||
+ "'123456789' = 123 terabytes and a bit less than a half\n"
|
||||
+)
|
||||
|
||||
ContainerType = namedtuple("ContainerType", ["name", "label"])
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
From 82ec245b104c4cc87f322b8824e04f22961c34d6 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Stodola <honza.stodola@gmail.com>
|
||||
Date: Mon, 31 Aug 2020 21:59:43 +0200
|
||||
Subject: [PATCH] The underline character should not be displayed
|
||||
|
||||
Fix anaconda showing "1 _storage device selected" on the advanced storage spoke.
|
||||
The call was accidentally? removed in 7b7616f
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/advanced_storage.py | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/advanced_storage.py b/pyanaconda/ui/gui/spokes/advanced_storage.py
|
||||
index 88405894e..e3ad33147 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/advanced_storage.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/advanced_storage.py
|
||||
@@ -632,6 +632,7 @@ class FilterSpoke(NormalSpoke):
|
||||
if count > 0:
|
||||
really_show(summary_button)
|
||||
label.set_text(summary)
|
||||
+ label.set_use_underline(True)
|
||||
else:
|
||||
really_hide(summary_button)
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
From d1bb8d1d49de9668e8afc697aef8166d6c5bfabe Mon Sep 17 00:00:00 2001
|
||||
From: t_feng <fengtao40@huawei.com>
|
||||
Date: Fri, 25 Sep 2020 23:16:04 +0800
|
||||
Subject: [PATCH] add dnf transaction timeout
|
||||
|
||||
---
|
||||
pyanaconda/core/constants.py | 3 +++
|
||||
pyanaconda/payload/dnf/payload.py | 7 ++++++-
|
||||
2 files changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pyanaconda/core/constants.py b/pyanaconda/core/constants.py
|
||||
index 0e4cc15..607f96c 100644
|
||||
--- a/pyanaconda/core/constants.py
|
||||
+++ b/pyanaconda/core/constants.py
|
||||
@@ -448,6 +448,9 @@ URL_TYPE_BASEURL = "BASEURL"
|
||||
URL_TYPE_MIRRORLIST = "MIRRORLIST"
|
||||
URL_TYPE_METALINK = "METALINK"
|
||||
|
||||
+#DNF trasactions timeout
|
||||
+DNF_TRANSACTIONS_TIMEOUT = 1800
|
||||
+
|
||||
# The default source for the DNF payload.
|
||||
DNF_DEFAULT_SOURCE_TYPE = SOURCE_TYPE_CLOSEST_MIRROR
|
||||
|
||||
diff --git a/pyanaconda/payload/dnf/payload.py b/pyanaconda/payload/dnf/payload.py
|
||||
index f927208..08963cc 100644
|
||||
--- a/pyanaconda/payload/dnf/payload.py
|
||||
+++ b/pyanaconda/payload/dnf/payload.py
|
||||
@@ -19,6 +19,7 @@
|
||||
import configparser
|
||||
import functools
|
||||
import multiprocessing
|
||||
+import queue
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
@@ -1356,7 +1357,11 @@ class DNFPayload(Payload):
|
||||
if errors.errorHandler.cb(exc) == errors.ERROR_RAISE:
|
||||
log.error("Installation failed: %r", exc)
|
||||
go_to_failure_limbo()
|
||||
- (token, msg) = queue_instance.get()
|
||||
+ try:
|
||||
+ (token, msg) = queue_instance.get(True, constants.DNF_TRANSACTIONS_TIMEOUT)
|
||||
+ except queue.Empty:
|
||||
+ msg = ("Payload error - DNF installation has timeouted")
|
||||
+ raise PayloadError(msg)
|
||||
|
||||
process.join()
|
||||
# Don't close the mother base here, because we still need it.
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
From 5dc9b2ee4dde7b6deb477b581759c5f76dcb87b5 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Fri, 19 Jun 2020 15:57:57 +0200
|
||||
Subject: [PATCH] Add tests for verify_valid_installtree function (#1844287)
|
||||
|
||||
It's testing if repodata/repomd.xml file exists.
|
||||
|
||||
Related: rhbz#1844287
|
||||
Related: rhbz#1849093
|
||||
---
|
||||
.../module_source_base_test.py | 23 ++++++++++++++++++-
|
||||
1 file changed, 22 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tests/nosetests/pyanaconda_tests/module_source_base_test.py b/tests/nosetests/pyanaconda_tests/module_source_base_test.py
|
||||
index f58e2b1639..3ba40edf4c 100644
|
||||
--- a/tests/nosetests/pyanaconda_tests/module_source_base_test.py
|
||||
+++ b/tests/nosetests/pyanaconda_tests/module_source_base_test.py
|
||||
@@ -16,6 +16,8 @@
|
||||
# Red Hat, Inc.
|
||||
#
|
||||
import unittest
|
||||
+from pathlib import Path
|
||||
+from tempfile import TemporaryDirectory
|
||||
from unittest.mock import patch
|
||||
|
||||
from pyanaconda.core.constants import INSTALL_TREE
|
||||
@@ -23,7 +25,8 @@
|
||||
from pyanaconda.modules.payloads.constants import SourceType
|
||||
from pyanaconda.modules.payloads.source.mount_tasks import SetUpMountTask, TearDownMountTask
|
||||
from pyanaconda.modules.payloads.source.source_base import MountingSourceMixin
|
||||
-from pyanaconda.modules.payloads.source.utils import find_and_mount_iso_image
|
||||
+from pyanaconda.modules.payloads.source.utils import find_and_mount_iso_image, \
|
||||
+ verify_valid_installtree
|
||||
|
||||
mount_location = "/some/dir"
|
||||
|
||||
@@ -184,3 +187,21 @@ def find_and_mount_iso_image_fail_mount_test(self,
|
||||
)
|
||||
|
||||
self.assertEqual(iso_name, "")
|
||||
+
|
||||
+ def verify_valid_installtree_success_test(self):
|
||||
+ """Test verify_valid_installtree functionality success."""
|
||||
+ with TemporaryDirectory() as tmp:
|
||||
+ repodir_path = Path(tmp, "repodata")
|
||||
+ repodir_path.mkdir()
|
||||
+ repomd_path = Path(repodir_path, "repomd.xml")
|
||||
+ repomd_path.write_text("This is a cool repomd file!")
|
||||
+
|
||||
+ self.assertTrue(verify_valid_installtree(tmp))
|
||||
+
|
||||
+ def verify_valid_installtree_failed_test(self):
|
||||
+ """Test verify_valid_installtree functionality failed."""
|
||||
+ with TemporaryDirectory() as tmp:
|
||||
+ repodir_path = Path(tmp, "repodata")
|
||||
+ repodir_path.mkdir()
|
||||
+
|
||||
+ self.assertFalse(verify_valid_installtree(tmp))
|
||||
@ -1,165 +0,0 @@
|
||||
From d7398bef83d12281fe95a7964b990b07bc56003b Mon Sep 17 00:00:00 2001
|
||||
From: Qiumiao Zhang <zhangqiumiao1@huawei.com>
|
||||
Date: Tue, 23 Aug 2022 17:32:01 +0800
|
||||
Subject: [PATCH] change the startup mode of do_transaction sub proces
|
||||
|
||||
---
|
||||
pyanaconda/payload/dnf/payload.py | 39 +++++++++++++++++++--
|
||||
pyanaconda/payload/dnf/utils.py | 58 ++++++++++++++++++++++++++++++-
|
||||
2 files changed, 93 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/payload/dnf/payload.py b/pyanaconda/payload/dnf/payload.py
|
||||
index 45003da..e473a68 100644
|
||||
--- a/pyanaconda/payload/dnf/payload.py
|
||||
+++ b/pyanaconda/payload/dnf/payload.py
|
||||
@@ -89,6 +89,9 @@ log = get_packaging_logger()
|
||||
|
||||
USER_AGENT = "%s (anaconda)/%s" % (productName, productVersion)
|
||||
|
||||
+g_include_list = []
|
||||
+g_exclude_list = []
|
||||
+
|
||||
__all__ = ["DNFPayload"]
|
||||
|
||||
|
||||
@@ -530,6 +533,10 @@ class DNFPayload(Payload):
|
||||
log.debug("transaction exclude list")
|
||||
log.debug(exclude_list)
|
||||
|
||||
+ global g_include_list, g_exclude_list
|
||||
+ g_include_list.extend(include_list)
|
||||
+ g_exclude_list.extend(exclude_list)
|
||||
+
|
||||
# feed it to DNF
|
||||
try:
|
||||
# FIXME: Remove self._base.conf.strict workaround when bz1761518 is fixed
|
||||
@@ -1327,9 +1334,35 @@ class DNFPayload(Payload):
|
||||
pre_msg = (N_("Preparing transaction from installation source"))
|
||||
progress_message(pre_msg)
|
||||
|
||||
- queue_instance = multiprocessing.Queue()
|
||||
- process = multiprocessing.Process(target=do_transaction,
|
||||
- args=(self._base, queue_instance))
|
||||
+ repos = dict()
|
||||
+ for repo in self._base.repos.iter_enabled():
|
||||
+ t_repo = dict()
|
||||
+ repo_agrs = dict()
|
||||
+ t_repo['baseurl'] = list(repo.baseurl)
|
||||
+ repo_agrs['sslverify'] = repo.sslverify
|
||||
+ repo_agrs['proxy'] = repo.proxy
|
||||
+ t_repo['repo_agrs'] = repo_agrs
|
||||
+ repos[repo.id] = t_repo
|
||||
+
|
||||
+ global g_include_list, g_exclude_list
|
||||
+
|
||||
+ ctx = multiprocessing.get_context('spawn')
|
||||
+ queue_instance = ctx.Queue()
|
||||
+ process = ctx.Process(target=do_transaction,
|
||||
+ args=(queue_instance, repos,
|
||||
+ self._base.conf.releasever,
|
||||
+ self._base.conf.installroot,
|
||||
+ self._base.conf.substitutions,
|
||||
+ self._base.conf.multilib_policy,
|
||||
+ self._base.conf.timeout,
|
||||
+ self._base.conf.retries,
|
||||
+ self._download_location,
|
||||
+ self._base.conf.proxy,
|
||||
+ self._base.conf.proxy_username,
|
||||
+ self._base.conf.proxy_password,
|
||||
+ g_include_list,
|
||||
+ g_exclude_list))
|
||||
+
|
||||
process.start()
|
||||
(token, msg) = queue_instance.get()
|
||||
# When the installation works correctly it will get 'install' updates
|
||||
diff --git a/pyanaconda/payload/dnf/utils.py b/pyanaconda/payload/dnf/utils.py
|
||||
index dfac5c9..23a11fd 100644
|
||||
--- a/pyanaconda/payload/dnf/utils.py
|
||||
+++ b/pyanaconda/payload/dnf/utils.py
|
||||
@@ -18,6 +18,7 @@
|
||||
import os
|
||||
import operator
|
||||
import time
|
||||
+import dnf
|
||||
|
||||
from blivet.size import Size
|
||||
|
||||
@@ -27,6 +28,7 @@ from pyanaconda.progress import progressQ
|
||||
from pyanaconda.core import util
|
||||
from pyanaconda.core.configuration.anaconda import conf
|
||||
from pyanaconda.product import productName, productVersion
|
||||
+from pyanaconda.flags import flags
|
||||
|
||||
log = get_packaging_logger()
|
||||
|
||||
@@ -121,12 +123,66 @@ def pick_mount_point(df, download_size, install_size, download_only):
|
||||
return sorted_mpoints[0][0]
|
||||
|
||||
|
||||
-def do_transaction(base, queue_instance):
|
||||
+def update_conf(conf, substitutions, releasever, installroot, multilib_policy, timeout, retries):
|
||||
+ conf.cachedir = DNF_CACHE_DIR
|
||||
+ conf.pluginconfpath = DNF_PLUGINCONF_DIR
|
||||
+ conf.logdir = '/tmp/'
|
||||
+ # enable depsolver debugging if in debug mode
|
||||
+ conf.debug_solver = flags.debug
|
||||
+
|
||||
+ conf.substitutions = substitutions
|
||||
+ conf.releasever = releasever
|
||||
+ conf.installroot = installroot
|
||||
+ conf.prepend_installroot('persistdir')
|
||||
+ conf.multilib_policy = multilib_policy
|
||||
+ conf.timeout = timeout
|
||||
+ conf.retries = retries
|
||||
+
|
||||
+ conf.substitutions.update_from_etc(conf.installroot)
|
||||
+
|
||||
+ conf.reposdir = REPO_DIRS
|
||||
+
|
||||
+
|
||||
+def update_proxy(conf, proxy, proxy_username, proxy_password):
|
||||
+ conf.proxy = proxy
|
||||
+ conf.proxy_username = proxy_username
|
||||
+ conf.proxy_password = proxy_password
|
||||
+
|
||||
+
|
||||
+def update_depdency(base, include_list, exclude_list):
|
||||
+ base.fill_sack()
|
||||
+ base.read_comps()
|
||||
+ base.install_specs(install=include_list, exclude=exclude_list)
|
||||
+ base.resolve()
|
||||
+
|
||||
+
|
||||
+def do_transaction(queue_instance, repos, releasever, installroot, substitutions,
|
||||
+ multilib_policy, timeout, retries, pkgdir, proxy,
|
||||
+ proxy_username, proxy_password, include_list, exclude_list):
|
||||
# Execute the DNF transaction and catch any errors. An error doesn't
|
||||
# always raise a BaseException, so presence of 'quit' without a preceeding
|
||||
# 'post' message also indicates a problem.
|
||||
try:
|
||||
display = TransactionProgress(queue_instance)
|
||||
+ # We create new dnf base obj, and update it from parent process
|
||||
+ base = dnf.Base()
|
||||
+ conf = base.conf
|
||||
+
|
||||
+ update_conf(conf, substitutions, releasever, installroot, multilib_policy, timeout, retries)
|
||||
+ update_proxy(conf, proxy, proxy_username, proxy_password)
|
||||
+
|
||||
+ queue_instance.put(('log', 'start to setup repo.'))
|
||||
+ for (key, repo) in repos.items():
|
||||
+ base.repos.add_new_repo(key, conf, repo['baseurl'], **repo['repo_agrs'])
|
||||
+ base.repos[key].enable()
|
||||
+
|
||||
+ for repo in base.repos.iter_enabled():
|
||||
+ repo.pkgdir = pkgdir
|
||||
+
|
||||
+ queue_instance.put(('log', 'start to update depdency.'))
|
||||
+ update_depdency(base, include_list, exclude_list)
|
||||
+
|
||||
+ queue_instance.put(('log', 'start to transaction.'))
|
||||
base.do_transaction(display=display)
|
||||
exit_reason = "DNF quit"
|
||||
except BaseException as e: # pylint: disable=broad-except
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -1,84 +0,0 @@
|
||||
From 5be52e7c3122634a1d7b011922356788315e22ec Mon Sep 17 00:00:00 2001
|
||||
From: root <root@localhost.localdomain>
|
||||
Date: Sun, 25 Apr 2021 22:27:18 +0800
|
||||
Subject: [PATCH] patch
|
||||
|
||||
---
|
||||
pyanaconda/core/constants.py | 1 +
|
||||
pyanaconda/modules/payloads/source/cdrom/initialization.py | 3 ++-
|
||||
pyanaconda/modules/payloads/source/utils.py | 4 ++--
|
||||
tests/nosetests/pyanaconda_tests/module_source_base_test.py | 3 +--
|
||||
4 files changed, 6 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/core/constants.py b/pyanaconda/core/constants.py
|
||||
index 4fc4b80..4724dc1 100644
|
||||
--- a/pyanaconda/core/constants.py
|
||||
+++ b/pyanaconda/core/constants.py
|
||||
@@ -53,6 +53,7 @@ DRACUT_ISODIR = "/run/install/source"
|
||||
ISO_DIR = MOUNT_DIR + "/isodir"
|
||||
IMAGE_DIR = MOUNT_DIR + "/image"
|
||||
INSTALL_TREE = MOUNT_DIR + "/source"
|
||||
+SOURCES_DIR = MOUNT_DIR + "/sources"
|
||||
BASE_REPO_NAME = "anaconda"
|
||||
|
||||
# Get list of repo names witch should be used as base repo
|
||||
diff --git a/pyanaconda/modules/payloads/source/cdrom/initialization.py b/pyanaconda/modules/payloads/source/cdrom/initialization.py
|
||||
index 7fc38fc..95303ea 100644
|
||||
--- a/pyanaconda/modules/payloads/source/cdrom/initialization.py
|
||||
+++ b/pyanaconda/modules/payloads/source/cdrom/initialization.py
|
||||
@@ -98,7 +98,8 @@ class SetUpCdromSourceTask(SetUpMountTask):
|
||||
try:
|
||||
device_data = DeviceData.from_structure(device_tree.GetDeviceData(dev_name))
|
||||
mount(device_data.path, self._target_mount, "iso9660", "ro")
|
||||
- except PayloadSetupError:
|
||||
+ except PayloadSetupError as e:
|
||||
+ log.debug("Failed to mount %s: %s", dev_name, str(e))
|
||||
continue
|
||||
|
||||
if is_valid_install_disk(self._target_mount):
|
||||
diff --git a/pyanaconda/modules/payloads/source/utils.py b/pyanaconda/modules/payloads/source/utils.py
|
||||
index a8e2f49..2dc4062 100644
|
||||
--- a/pyanaconda/modules/payloads/source/utils.py
|
||||
+++ b/pyanaconda/modules/payloads/source/utils.py
|
||||
@@ -20,7 +20,7 @@ import os.path
|
||||
from blivet.arch import get_arch
|
||||
from blivet.util import mount
|
||||
|
||||
-from pyanaconda.core.constants import INSTALL_TREE
|
||||
+from pyanaconda.core.constants import SOURCES_DIR
|
||||
from pyanaconda.core.storage import device_matches
|
||||
from pyanaconda.core.util import join_paths
|
||||
from pyanaconda.payload.image import find_first_iso_image
|
||||
@@ -177,7 +177,7 @@ class MountPointGenerator:
|
||||
:rtype: str
|
||||
"""
|
||||
path = "{}/mount-{:0>4}-{}".format(
|
||||
- INSTALL_TREE,
|
||||
+ SOURCES_DIR,
|
||||
cls._counter,
|
||||
suffix
|
||||
)
|
||||
diff --git a/tests/nosetests/pyanaconda_tests/module_source_base_test.py b/tests/nosetests/pyanaconda_tests/module_source_base_test.py
|
||||
index c9f00fa..2d1a1da 100644
|
||||
--- a/tests/nosetests/pyanaconda_tests/module_source_base_test.py
|
||||
+++ b/tests/nosetests/pyanaconda_tests/module_source_base_test.py
|
||||
@@ -20,7 +20,6 @@ from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from unittest.mock import patch
|
||||
|
||||
-from pyanaconda.core.constants import INSTALL_TREE
|
||||
from pyanaconda.modules.common.errors.payload import SourceSetupError, SourceTearDownError
|
||||
from pyanaconda.modules.payloads.constants import SourceType
|
||||
from pyanaconda.modules.payloads.source.mount_tasks import SetUpMountTask, TearDownMountTask
|
||||
@@ -55,7 +54,7 @@ class MountingSourceMixinTestCase(unittest.TestCase):
|
||||
def counter_test(self):
|
||||
"""Mount path in mount source base gets incremental numbers."""
|
||||
module = DummyMountingSourceSubclass()
|
||||
- self.assertTrue(module.mount_point.startswith(INSTALL_TREE + "/mount-"))
|
||||
+ self.assertTrue(module.mount_point.startswith("/run/install/sources/mount-"))
|
||||
first_counter = int(module.mount_point.split("-")[1])
|
||||
|
||||
module = DummyMountingSourceSubclass()
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
From 6cee8e5a59a9c424d2bc79b5474a749c4f786b40 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Fri, 19 Jun 2020 14:12:21 +0200
|
||||
Subject: [PATCH] Do not test if repo is valid based on .treeinfo file
|
||||
(#1844287)
|
||||
|
||||
Not all repositories need to have .treeinfo file. When it is not a compose but
|
||||
only a third party repo it's probably created by just running createrepo_c which
|
||||
does not create this file. We do not want to disable these repositories.
|
||||
|
||||
So instead check that repodata/repomd.xml file is present. Based on my
|
||||
discussion with DNF/RPM developers it seems like the best approach.
|
||||
|
||||
Resolves: rhbz#1844287
|
||||
Resolves: rhbz#1849093
|
||||
|
||||
Reported-by: Adam Williamson <awilliam@redhat.com>
|
||||
---
|
||||
pyanaconda/payload/image.py | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/payload/image.py b/pyanaconda/payload/image.py
|
||||
index b76b33db40..4b6d0c7bb9 100644
|
||||
--- a/pyanaconda/payload/image.py
|
||||
+++ b/pyanaconda/payload/image.py
|
||||
@@ -28,6 +28,7 @@
|
||||
from blivet.size import Size
|
||||
|
||||
from pyanaconda import isys
|
||||
+from pyanaconda.core.util import join_paths
|
||||
from pyanaconda.errors import errorHandler, ERROR_RAISE, InvalidImageSizeError, MissingImageError
|
||||
from pyanaconda.modules.common.constants.objects import DEVICE_TREE
|
||||
from pyanaconda.modules.common.constants.services import STORAGE
|
||||
@@ -129,16 +130,15 @@ def find_first_iso_image(path, mount_path="/mnt/install/cdimage"):
|
||||
|
||||
|
||||
def verify_valid_installtree(path):
|
||||
- """Check if the given path is a valid installtree repository
|
||||
+ """Check if the given path is a valid installtree repository.
|
||||
|
||||
:param str path: install tree path
|
||||
:returns: True if repository is valid false otherwise
|
||||
:rtype: bool
|
||||
"""
|
||||
- # TODO: This can be enhanced to check for repodata folder.
|
||||
- if os.path.exists(os.path.join(path, ".treeinfo")):
|
||||
- return True
|
||||
- elif os.path.exists(os.path.join(path, "treeinfo")):
|
||||
+ repomd_path = join_paths(path, "repodata/repomd.xml")
|
||||
+
|
||||
+ if os.path.exists(repomd_path) and os.path.isfile(repomd_path):
|
||||
return True
|
||||
|
||||
return False
|
||||
@ -1,29 +0,0 @@
|
||||
From 19264b192083d5cf38750a9cef0ec0a55eea3cfe Mon Sep 17 00:00:00 2001
|
||||
From: zhangqiumiao <zhangqiumiao1@huawei.com>
|
||||
Date: Thu, 10 Sep 2020 14:59:14 +0800
|
||||
Subject: [PATCH] bugfix fix password policy
|
||||
|
||||
---
|
||||
data/interactive-defaults.ks | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/data/interactive-defaults.ks b/data/interactive-defaults.ks
|
||||
index 0177cf9..7e43a39 100644
|
||||
--- a/data/interactive-defaults.ks
|
||||
+++ b/data/interactive-defaults.ks
|
||||
@@ -4,9 +4,9 @@ firstboot --enable
|
||||
|
||||
%anaconda
|
||||
# Default password policies
|
||||
-pwpolicy root --notstrict --minlen=8 --minquality=1 --nochanges --notempty
|
||||
-pwpolicy user --notstrict --minlen=8 --minquality=1 --nochanges --emptyok
|
||||
-pwpolicy luks --notstrict --minlen=8 --minquality=1 --nochanges --notempty
|
||||
+pwpolicy root --strict --minlen=8 --minquality=1 --nochanges --notempty
|
||||
+pwpolicy user --strict --minlen=8 --minquality=1 --nochanges --emptyok
|
||||
+pwpolicy luks --strict --minlen=8 --minquality=1 --nochanges --notempty
|
||||
# NOTE: This applies only to *fully* interactive installations, partial kickstart
|
||||
# installations use defaults specified in pyanaconda/pwpolicy.py.
|
||||
# Automated kickstart installs simply ignore the password policy as the policy
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
From 3e4a2bd7fd23c458a96b387c4df9f4abb984d59f Mon Sep 17 00:00:00 2001
|
||||
From: t_feng <fengtao40@huawei.com>
|
||||
Date: Thu, 18 Jun 2020 22:30:28 +0800
|
||||
Subject: [PATCH] bugfix logo display in low screen resolution
|
||||
|
||||
---
|
||||
data/anaconda-gtk.css | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/data/anaconda-gtk.css b/data/anaconda-gtk.css
|
||||
index c47bb87..7b7166b 100644
|
||||
--- a/data/anaconda-gtk.css
|
||||
+++ b/data/anaconda-gtk.css
|
||||
@@ -113,6 +113,7 @@ infobar.error {
|
||||
.logo {
|
||||
background-image: url('/usr/share/anaconda/pixmaps/sidebar-logo.png');
|
||||
background-position: 50% 20px;
|
||||
+ background-size: 90%;
|
||||
background-repeat: no-repeat;
|
||||
background-color: transparent;
|
||||
}
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,107 +0,0 @@
|
||||
From fea8f2db7594482457f1a7f7aebb7ccac4505fa5 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Fri, 19 Jun 2020 15:36:37 +0200
|
||||
Subject: [PATCH] Move verify_valid_installtree to source module utils
|
||||
(#1844287)
|
||||
|
||||
It's used only by modules now. We can safely move it.
|
||||
|
||||
Related: rhbz#1844287
|
||||
Related: rhbz#1849093
|
||||
---
|
||||
.../payloads/source/harddrive/initialization.py | 3 +--
|
||||
.../payloads/source/nfs/initialization.py | 4 ++--
|
||||
pyanaconda/modules/payloads/source/utils.py | 15 +++++++++++++++
|
||||
pyanaconda/payload/image.py | 16 ----------------
|
||||
4 files changed, 18 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/payloads/source/harddrive/initialization.py b/pyanaconda/modules/payloads/source/harddrive/initialization.py
|
||||
index 38d777adca..ed77db6bc9 100644
|
||||
--- a/pyanaconda/modules/payloads/source/harddrive/initialization.py
|
||||
+++ b/pyanaconda/modules/payloads/source/harddrive/initialization.py
|
||||
@@ -22,8 +22,7 @@
|
||||
from pyanaconda.modules.common.errors.payload import SourceSetupError
|
||||
from pyanaconda.modules.common.task import Task
|
||||
from pyanaconda.modules.payloads.source.utils import find_and_mount_device, \
|
||||
- find_and_mount_iso_image
|
||||
-from pyanaconda.payload.image import verify_valid_installtree
|
||||
+ find_and_mount_iso_image, verify_valid_installtree
|
||||
from pyanaconda.payload.utils import unmount
|
||||
from pyanaconda.anaconda_loggers import get_module_logger
|
||||
|
||||
diff --git a/pyanaconda/modules/payloads/source/nfs/initialization.py b/pyanaconda/modules/payloads/source/nfs/initialization.py
|
||||
index 00112c3ecb..56e95060c6 100644
|
||||
--- a/pyanaconda/modules/payloads/source/nfs/initialization.py
|
||||
+++ b/pyanaconda/modules/payloads/source/nfs/initialization.py
|
||||
@@ -21,9 +21,9 @@
|
||||
from pyanaconda.core.payload import parse_nfs_url
|
||||
from pyanaconda.modules.common.errors.payload import SourceSetupError
|
||||
from pyanaconda.modules.common.task import Task
|
||||
-from pyanaconda.modules.payloads.source.utils import find_and_mount_iso_image
|
||||
+from pyanaconda.modules.payloads.source.utils import find_and_mount_iso_image, \
|
||||
+ verify_valid_installtree
|
||||
from pyanaconda.payload.errors import PayloadSetupError
|
||||
-from pyanaconda.payload.image import verify_valid_installtree
|
||||
from pyanaconda.payload.utils import mount, unmount
|
||||
|
||||
log = get_module_logger(__name__)
|
||||
diff --git a/pyanaconda/modules/payloads/source/utils.py b/pyanaconda/modules/payloads/source/utils.py
|
||||
index b9642a945c..ed9e5da49b 100644
|
||||
--- a/pyanaconda/modules/payloads/source/utils.py
|
||||
+++ b/pyanaconda/modules/payloads/source/utils.py
|
||||
@@ -148,6 +148,21 @@ def _create_iso_path(path, iso_name):
|
||||
return path
|
||||
|
||||
|
||||
+def verify_valid_installtree(path):
|
||||
+ """Check if the given path is a valid installtree repository.
|
||||
+
|
||||
+ :param str path: install tree path
|
||||
+ :returns: True if repository is valid false otherwise
|
||||
+ :rtype: bool
|
||||
+ """
|
||||
+ repomd_path = join_paths(path, "repodata/repomd.xml")
|
||||
+
|
||||
+ if os.path.exists(repomd_path) and os.path.isfile(repomd_path):
|
||||
+ return True
|
||||
+
|
||||
+ return False
|
||||
+
|
||||
+
|
||||
class MountPointGenerator:
|
||||
_counter = 0
|
||||
|
||||
diff --git a/pyanaconda/payload/image.py b/pyanaconda/payload/image.py
|
||||
index 4b6d0c7bb9..9401e29388 100644
|
||||
--- a/pyanaconda/payload/image.py
|
||||
+++ b/pyanaconda/payload/image.py
|
||||
@@ -28,7 +28,6 @@
|
||||
from blivet.size import Size
|
||||
|
||||
from pyanaconda import isys
|
||||
-from pyanaconda.core.util import join_paths
|
||||
from pyanaconda.errors import errorHandler, ERROR_RAISE, InvalidImageSizeError, MissingImageError
|
||||
from pyanaconda.modules.common.constants.objects import DEVICE_TREE
|
||||
from pyanaconda.modules.common.constants.services import STORAGE
|
||||
@@ -129,21 +128,6 @@ def find_first_iso_image(path, mount_path="/mnt/install/cdimage"):
|
||||
return None
|
||||
|
||||
|
||||
-def verify_valid_installtree(path):
|
||||
- """Check if the given path is a valid installtree repository.
|
||||
-
|
||||
- :param str path: install tree path
|
||||
- :returns: True if repository is valid false otherwise
|
||||
- :rtype: bool
|
||||
- """
|
||||
- repomd_path = join_paths(path, "repodata/repomd.xml")
|
||||
-
|
||||
- if os.path.exists(repomd_path) and os.path.isfile(repomd_path):
|
||||
- return True
|
||||
-
|
||||
- return False
|
||||
-
|
||||
-
|
||||
def _check_repodata(mount_path):
|
||||
install_tree_meta = InstallTreeMetadata()
|
||||
if not install_tree_meta.load_file(mount_path):
|
||||
@ -1,59 +0,0 @@
|
||||
From 7ab2db63f7d5f30035d6db2ec2a86a156c50d2f6 Mon Sep 17 00:00:00 2001
|
||||
From: Radek Vykydal <rvykydal@redhat.com>
|
||||
Date: Wed, 19 Aug 2020 13:50:48 +0200
|
||||
Subject: [PATCH] network: add timeout for synchronous activation of a
|
||||
connection
|
||||
|
||||
Related: rhbz#1869323
|
||||
---
|
||||
pyanaconda/modules/network/constants.py | 1 +
|
||||
pyanaconda/modules/network/nm_client.py | 13 ++++++++++---
|
||||
2 files changed, 11 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/network/constants.py b/pyanaconda/modules/network/constants.py
|
||||
index 33c99d76e..530a8e281 100644
|
||||
--- a/pyanaconda/modules/network/constants.py
|
||||
+++ b/pyanaconda/modules/network/constants.py
|
||||
@@ -24,6 +24,7 @@ from pyanaconda.core.constants import FIREWALL_DEFAULT, FIREWALL_DISABLED, \
|
||||
|
||||
|
||||
NM_CONNECTION_UUID_LENGTH = 36
|
||||
+CONNECTION_ACTIVATION_TIMEOUT = 45
|
||||
|
||||
|
||||
@unique
|
||||
diff --git a/pyanaconda/modules/network/nm_client.py b/pyanaconda/modules/network/nm_client.py
|
||||
index 5e1fb854e..2f5703e76 100644
|
||||
--- a/pyanaconda/modules/network/nm_client.py
|
||||
+++ b/pyanaconda/modules/network/nm_client.py
|
||||
@@ -23,9 +23,10 @@ gi.require_version("NM", "1.0")
|
||||
from gi.repository import NM
|
||||
|
||||
import socket
|
||||
-from queue import Queue
|
||||
+from queue import Queue, Empty
|
||||
from pykickstart.constants import BIND_TO_MAC
|
||||
-from pyanaconda.modules.network.constants import NM_CONNECTION_UUID_LENGTH
|
||||
+from pyanaconda.modules.network.constants import NM_CONNECTION_UUID_LENGTH, \
|
||||
+ CONNECTION_ACTIVATION_TIMEOUT
|
||||
from pyanaconda.modules.network.kickstart import default_ks_vlan_interface_name
|
||||
from pyanaconda.modules.network.utils import is_s390, get_s390_settings, netmask2prefix, \
|
||||
prefix2netmask
|
||||
@@ -939,7 +940,13 @@ def activate_connection_sync(nm_client, connection, device):
|
||||
sync_queue
|
||||
)
|
||||
|
||||
- return sync_queue.get()
|
||||
+ try:
|
||||
+ ret = sync_queue.get(timeout=CONNECTION_ACTIVATION_TIMEOUT)
|
||||
+ except Empty:
|
||||
+ log.error("Activation of a connection timed out.")
|
||||
+ ret = None
|
||||
+
|
||||
+ return ret
|
||||
|
||||
|
||||
def get_dracut_arguments_from_connection(nm_client, connection, iface, target_ip,
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
From a3e46c49216f76f73097587b15ded52b253ce3d2 Mon Sep 17 00:00:00 2001
|
||||
From: Radek Vykydal <rvykydal@redhat.com>
|
||||
Date: Wed, 26 Aug 2020 09:52:24 +0200
|
||||
Subject: [PATCH] network: do not crash when updating a connection without
|
||||
wired settings
|
||||
|
||||
One of the Anaconda fallouts of NM defaulting to keyfiles.
|
||||
Hit by team-pre and five other -pre kickstart tests.
|
||||
---
|
||||
pyanaconda/modules/network/initialization.py | 15 ++++++++-------
|
||||
1 file changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/network/initialization.py b/pyanaconda/modules/network/initialization.py
|
||||
index 5e33d0494..b27a46976 100644
|
||||
--- a/pyanaconda/modules/network/initialization.py
|
||||
+++ b/pyanaconda/modules/network/initialization.py
|
||||
@@ -411,13 +411,14 @@ class DumpMissingIfcfgFilesTask(Task):
|
||||
s_con.set_property(NM.SETTING_CONNECTION_ID, iface)
|
||||
s_con.set_property(NM.SETTING_CONNECTION_INTERFACE_NAME, iface)
|
||||
s_wired = con.get_setting_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)
|
||||
- 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",
|
||||
- self.name, iface, bound_mac)
|
||||
+ 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)
|
||||
+ 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",
|
||||
+ self.name, iface, bound_mac)
|
||||
|
||||
@guard_by_system_configuration(return_value=[])
|
||||
def run(self):
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
From 6ffa54ed7ca56047b26f05cc6b9967820fa5dc21 Mon Sep 17 00:00:00 2001
|
||||
From: Radek Vykydal <rvykydal@redhat.com>
|
||||
Date: Wed, 19 Aug 2020 13:51:14 +0200
|
||||
Subject: [PATCH] network: do not try to activate connection that has not been
|
||||
found
|
||||
|
||||
Resolves: rhbz#1869323
|
||||
---
|
||||
pyanaconda/modules/network/nm_client.py | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/network/nm_client.py b/pyanaconda/modules/network/nm_client.py
|
||||
index 2f5703e76..acf6f7858 100644
|
||||
--- a/pyanaconda/modules/network/nm_client.py
|
||||
+++ b/pyanaconda/modules/network/nm_client.py
|
||||
@@ -785,8 +785,9 @@ def ensure_active_connection_for_device(nm_client, uuid, device_name, only_repla
|
||||
active_uuid = ac.get_uuid() if ac else None
|
||||
if uuid != active_uuid:
|
||||
ifcfg_con = nm_client.get_connection_by_uuid(uuid)
|
||||
- activate_connection_sync(nm_client, ifcfg_con, None)
|
||||
- activated = True
|
||||
+ if ifcfg_con:
|
||||
+ activate_connection_sync(nm_client, ifcfg_con, None)
|
||||
+ activated = True
|
||||
msg = "activated" if activated else "not activated"
|
||||
log.debug("ensure active ifcfg connection for %s (%s -> %s): %s",
|
||||
device_name, active_uuid, uuid, msg)
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
From 787daf49b358fbe2d514012a708c28575fc8122b Mon Sep 17 00:00:00 2001
|
||||
From: Radek Vykydal <rvykydal@redhat.com>
|
||||
Date: Wed, 1 Jul 2020 11:25:37 +0200
|
||||
Subject: [PATCH] network: fix configuration of virtual devices by boot options
|
||||
|
||||
The configuration was not passed to installed system via ifcfg files.
|
||||
|
||||
Resolves: rhbz#1851218
|
||||
---
|
||||
pyanaconda/modules/network/initialization.py | 17 ++++++++++++-----
|
||||
1 file changed, 12 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/network/initialization.py b/pyanaconda/modules/network/initialization.py
|
||||
index de1ec851b..5e33d0494 100644
|
||||
--- a/pyanaconda/modules/network/initialization.py
|
||||
+++ b/pyanaconda/modules/network/initialization.py
|
||||
@@ -26,7 +26,8 @@ from pyanaconda.modules.network.nm_client import get_device_name_from_network_da
|
||||
update_connection_values, commit_changes_with_autoconnection_blocked, is_ibft_connection
|
||||
from pyanaconda.modules.network.ifcfg import get_ifcfg_file_of_device, find_ifcfg_uuid_of_device, \
|
||||
get_master_slaves_from_ifcfgs
|
||||
-from pyanaconda.modules.network.device_configuration import supported_wired_device_types
|
||||
+from pyanaconda.modules.network.device_configuration import supported_wired_device_types, \
|
||||
+ virtual_device_types
|
||||
from pyanaconda.modules.network.utils import guard_by_system_configuration
|
||||
|
||||
log = get_module_logger(__name__)
|
||||
@@ -431,8 +432,9 @@ class DumpMissingIfcfgFilesTask(Task):
|
||||
log.debug("%s: No NetworkManager available.", self.name)
|
||||
return new_ifcfgs
|
||||
|
||||
+ dumped_device_types = supported_wired_device_types + virtual_device_types
|
||||
for device in self._nm_client.get_devices():
|
||||
- if device.get_device_type() not in supported_wired_device_types:
|
||||
+ if device.get_device_type() not in dumped_device_types:
|
||||
continue
|
||||
|
||||
iface = device.get_iface()
|
||||
@@ -446,9 +448,14 @@ class DumpMissingIfcfgFilesTask(Task):
|
||||
|
||||
device_is_slave = any(con.get_setting_connection().get_master() for con in cons)
|
||||
if device_is_slave:
|
||||
- log.debug("%s: not creating default connection for slave device %s",
|
||||
- self.name, iface)
|
||||
- continue
|
||||
+ # We have to dump persistent ifcfg files for slaves created in initramfs
|
||||
+ if n_cons == 1 and self._is_initramfs_connection(cons[0], iface):
|
||||
+ log.debug("%s: device %s has an initramfs slave connection",
|
||||
+ self.name, iface)
|
||||
+ else:
|
||||
+ log.debug("%s: not creating default connection for slave device %s",
|
||||
+ self.name, iface)
|
||||
+ continue
|
||||
|
||||
# Devices activated in initramfs should have ONBOOT=yes
|
||||
has_initramfs_con = any(self._is_initramfs_connection(con, iface) for con in cons)
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,95 +0,0 @@
|
||||
From 0b4867eba60bbee4b8e1c1bd58966691dd1c2431 Mon Sep 17 00:00:00 2001
|
||||
From: Radek Vykydal <rvykydal@redhat.com>
|
||||
Date: Wed, 5 Aug 2020 16:35:34 +0200
|
||||
Subject: [PATCH] network: fix parsing of hostname from ip= if mac is defined
|
||||
in dhcp
|
||||
|
||||
Resolves: rhbz#1852560
|
||||
---
|
||||
pyanaconda/core/regexes.py | 3 +++
|
||||
pyanaconda/network.py | 13 ++++++++-----
|
||||
tests/nosetests/pyanaconda_tests/network_test.py | 11 ++++++++---
|
||||
3 files changed, 19 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/core/regexes.py b/pyanaconda/core/regexes.py
|
||||
index 63ab668c9..ee5cc3765 100644
|
||||
--- a/pyanaconda/core/regexes.py
|
||||
+++ b/pyanaconda/core/regexes.py
|
||||
@@ -191,3 +191,6 @@ ZFCP_WWPN_NUMBER = re.compile(r'^(?:0x|)[0-9A-Fa-f]{16}$')
|
||||
|
||||
# IPv6 address in dracut IP option (including the square brackets)
|
||||
IPV6_ADDRESS_IN_DRACUT_IP_OPTION = re.compile(r'\[[^\]]+\]')
|
||||
+
|
||||
+# Octet of MAC address
|
||||
+MAC_OCTET = re.compile(r'[a-fA-F0-9][a-fA-F0-9]')
|
||||
diff --git a/pyanaconda/network.py b/pyanaconda/network.py
|
||||
index c66f35d44..7ba821fe4 100644
|
||||
--- a/pyanaconda/network.py
|
||||
+++ b/pyanaconda/network.py
|
||||
@@ -32,7 +32,7 @@ from pyanaconda.core import util, constants
|
||||
from pyanaconda.core.i18n import _
|
||||
from pyanaconda.core.kernel import kernel_arguments
|
||||
from pyanaconda.core.regexes import HOSTNAME_PATTERN_WITHOUT_ANCHORS, \
|
||||
- IPV6_ADDRESS_IN_DRACUT_IP_OPTION
|
||||
+ IPV6_ADDRESS_IN_DRACUT_IP_OPTION, MAC_OCTET
|
||||
from pyanaconda.core.configuration.anaconda import conf
|
||||
from pyanaconda.core.constants import TIME_SOURCE_SERVER
|
||||
from pyanaconda.modules.common.constants.services import NETWORK, TIMEZONE, STORAGE
|
||||
@@ -209,7 +209,7 @@ def hostname_from_cmdline(kernel_args):
|
||||
"""
|
||||
# legacy hostname= option
|
||||
hostname = kernel_args.get('hostname', "")
|
||||
- # ip= option
|
||||
+ # ip= option (man dracut.cmdline)
|
||||
ipopts = kernel_args.get('ip')
|
||||
# Example (2 options):
|
||||
# ens3:dhcp 10.34.102.244::10.34.102.54:255.255.255.0:myhostname:ens9:none
|
||||
@@ -219,10 +219,13 @@ def hostname_from_cmdline(kernel_args):
|
||||
# Replace ipv6 addresses with empty string, example of ipv6 config:
|
||||
# [fd00:10:100::84:5]::[fd00:10:100::86:49]:80:myhostname:ens9:none
|
||||
ipopt = IPV6_ADDRESS_IN_DRACUT_IP_OPTION.sub('', ipopt)
|
||||
- try:
|
||||
+ elements = ipopt.split(':')
|
||||
+ # Hostname can be defined only in option having more than 6 elements.
|
||||
+ # But filter out auto ip= with mac address set by MAC_OCTET matching, eg:
|
||||
+ # ip=<interface>:dhcp::52:54:00:12:34:56
|
||||
+ # where the 4th element is not hostname.
|
||||
+ if len(elements) > 6 and not re.match(MAC_OCTET, elements[6]):
|
||||
hostname = ipopt.split(':')[4]
|
||||
- except IndexError:
|
||||
- pass
|
||||
return hostname
|
||||
|
||||
|
||||
diff --git a/tests/nosetests/pyanaconda_tests/network_test.py b/tests/nosetests/pyanaconda_tests/network_test.py
|
||||
index e7ca630a7..161e883ff 100644
|
||||
--- a/tests/nosetests/pyanaconda_tests/network_test.py
|
||||
+++ b/tests/nosetests/pyanaconda_tests/network_test.py
|
||||
@@ -233,9 +233,11 @@ class NetworkTests(unittest.TestCase):
|
||||
cmdline = {"ip": "10.34.102.244::10.34.102.54:255.255.255.0:myhostname:ens9:none",
|
||||
"hostname": "hostname_bootopt"}
|
||||
self.assertEqual(network.hostname_from_cmdline(cmdline), "myhostname")
|
||||
- cmdline = {"ip": "ens3:dhcp "}
|
||||
+ cmdline = {"ip": "ens3:dhcp"}
|
||||
self.assertEqual(network.hostname_from_cmdline(cmdline), "")
|
||||
- cmdline = {"ip": "ens3:dhcp ",
|
||||
+ cmdline = {"ip": "ens3:dhcp:1500"}
|
||||
+ self.assertEqual(network.hostname_from_cmdline(cmdline), "")
|
||||
+ cmdline = {"ip": "ens3:dhcp",
|
||||
"hostname": "hostname_bootopt"}
|
||||
self.assertEqual(network.hostname_from_cmdline(cmdline), "hostname_bootopt")
|
||||
# two ip configurations
|
||||
@@ -248,6 +250,9 @@ class NetworkTests(unittest.TestCase):
|
||||
self.assertEqual(network.hostname_from_cmdline(cmdline), "myhostname")
|
||||
cmdline = {"ip": "[fd00:10:100::84:5]::[fd00:10:100::86:49]:80::ens50:none"}
|
||||
self.assertEqual(network.hostname_from_cmdline(cmdline), "")
|
||||
- cmdline = {"ip": "[fd00:10:100::84:5]::[fd00:10:100::86:49]:80::ens50:none"
|
||||
+ cmdline = {"ip": "[fd00:10:100::84:5]::[fd00:10:100::86:49]:80::ens50:none "
|
||||
"ens3:dhcp 10.34.102.244::10.34.102.54:255.255.255.0:myhostname:ens9:none"}
|
||||
self.assertEqual(network.hostname_from_cmdline(cmdline), "myhostname")
|
||||
+ # automatic ip= whith MAC address set
|
||||
+ cmdline = {"ip": "ens3:dhcp::52:54:00:12:34:56"}
|
||||
+ self.assertEqual(network.hostname_from_cmdline(cmdline), "")
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
From 72c5df1cb3ee8636fc6901aaf6192f7e147ed399 Mon Sep 17 00:00:00 2001
|
||||
From: Radek Vykydal <rvykydal@redhat.com>
|
||||
Date: Wed, 9 Sep 2020 15:36:35 +0200
|
||||
Subject: [PATCH] network: get hwadddr when binding to mac more robustly
|
||||
|
||||
---
|
||||
pyanaconda/modules/network/nm_client.py | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/network/nm_client.py b/pyanaconda/modules/network/nm_client.py
|
||||
index 4473c0110..04ae78d90 100644
|
||||
--- a/pyanaconda/modules/network/nm_client.py
|
||||
+++ b/pyanaconda/modules/network/nm_client.py
|
||||
@@ -695,7 +695,11 @@ def bind_settings_to_mac(nm_client, s_connection, s_wired, device_name=None, bin
|
||||
return False
|
||||
device = nm_client.get_device_by_iface(iface)
|
||||
if device:
|
||||
- hwaddr = device.get_permanent_hw_address() or device.get_hw_address()
|
||||
+ try:
|
||||
+ perm_hwaddr = device.get_permanent_hw_address()
|
||||
+ except AttributeError:
|
||||
+ perm_hwaddr = None
|
||||
+ hwaddr = perm_hwaddr or device.get_hw_address()
|
||||
s_wired.props.mac_address = hwaddr
|
||||
log.debug("Bind to mac: bound to %s", hwaddr)
|
||||
modified = True
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
From 1c7eed3607410d62324e368cc4fe9fb3f541cc48 Mon Sep 17 00:00:00 2001
|
||||
From: eaglegai <eaglegai@163.com>
|
||||
Date: Thu, 13 Jan 2022 18:49:29 +0800
|
||||
Subject: [PATCH] remove flatpack support
|
||||
|
||||
---
|
||||
pyanaconda/anaconda.py | 9 ++-------
|
||||
1 file changed, 2 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/anaconda.py b/pyanaconda/anaconda.py
|
||||
index 8c54011..c1108f2 100644
|
||||
--- a/pyanaconda/anaconda.py
|
||||
+++ b/pyanaconda/anaconda.py
|
||||
@@ -28,7 +28,6 @@ from pyanaconda.core.constants import DisplayModes
|
||||
from pyanaconda.core import constants
|
||||
from pyanaconda.core.startup.dbus_launcher import AnacondaDBusLauncher
|
||||
from pyanaconda.payload.source import SourceFactory, PayloadSourceTypeUnrecognized
|
||||
-from pyanaconda.payload.flatpak import FlatpakPayload
|
||||
|
||||
from pyanaconda.anaconda_loggers import get_stdout_logger
|
||||
stdoutLog = get_stdout_logger()
|
||||
@@ -79,12 +78,8 @@ class Anaconda(object):
|
||||
# class. If it doesn't give us one, fall back to the default.
|
||||
if not self._payload:
|
||||
if self.ksdata.ostreesetup.seen:
|
||||
- if FlatpakPayload.is_available():
|
||||
- from pyanaconda.payload.rpmostreepayload import RPMOSTreePayloadWithFlatpaks
|
||||
- klass = RPMOSTreePayloadWithFlatpaks
|
||||
- else:
|
||||
- from pyanaconda.payload.rpmostreepayload import RPMOSTreePayload
|
||||
- klass = RPMOSTreePayload
|
||||
+ from pyanaconda.payload.rpmostreepayload import RPMOSTreePayload
|
||||
+ klass = RPMOSTreePayload
|
||||
elif self.opts.liveinst:
|
||||
from pyanaconda.payload.live import LiveOSPayload
|
||||
klass = LiveOSPayload
|
||||
--
|
||||
2.30.0
|
||||
@ -1,228 +0,0 @@
|
||||
From 92d8d9d3e39eae8e268e3aeff096105b441bbeae Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Konecny <jkonecny@redhat.com>
|
||||
Date: Mon, 22 Jun 2020 13:12:53 +0200
|
||||
Subject: [PATCH] Rename function for a simple check for DNF repository
|
||||
|
||||
It's more clear to use repository in the name than installtree.
|
||||
|
||||
Related: rhbz#1844287
|
||||
Related: rhbz#1849093
|
||||
---
|
||||
.../payloads/source/harddrive/initialization.py | 4 ++--
|
||||
.../modules/payloads/source/nfs/initialization.py | 4 ++--
|
||||
pyanaconda/modules/payloads/source/utils.py | 6 +++---
|
||||
.../pyanaconda_tests/module_source_base_test.py | 14 +++++++-------
|
||||
.../module_source_harddrive_test.py | 12 ++++++------
|
||||
.../pyanaconda_tests/module_source_nfs_test.py | 12 ++++++------
|
||||
6 files changed, 26 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/payloads/source/harddrive/initialization.py b/pyanaconda/modules/payloads/source/harddrive/initialization.py
|
||||
index ed77db6bc9..004df4f034 100644
|
||||
--- a/pyanaconda/modules/payloads/source/harddrive/initialization.py
|
||||
+++ b/pyanaconda/modules/payloads/source/harddrive/initialization.py
|
||||
@@ -22,7 +22,7 @@
|
||||
from pyanaconda.modules.common.errors.payload import SourceSetupError
|
||||
from pyanaconda.modules.common.task import Task
|
||||
from pyanaconda.modules.payloads.source.utils import find_and_mount_device, \
|
||||
- find_and_mount_iso_image, verify_valid_installtree
|
||||
+ find_and_mount_iso_image, verify_valid_repository
|
||||
from pyanaconda.payload.utils import unmount
|
||||
from pyanaconda.anaconda_loggers import get_module_logger
|
||||
|
||||
@@ -82,7 +82,7 @@ def run(self):
|
||||
log.debug("Using the ISO '%s' mounted at '%s'.", iso_name, self._iso_mount)
|
||||
return SetupHardDriveResult(self._iso_mount, iso_name)
|
||||
|
||||
- if verify_valid_installtree(full_path_on_mounted_device):
|
||||
+ if verify_valid_repository(full_path_on_mounted_device):
|
||||
log.debug("Using the directory at '%s'.", full_path_on_mounted_device)
|
||||
return SetupHardDriveResult(full_path_on_mounted_device, "")
|
||||
|
||||
diff --git a/pyanaconda/modules/payloads/source/nfs/initialization.py b/pyanaconda/modules/payloads/source/nfs/initialization.py
|
||||
index 56e95060c6..99601bf325 100644
|
||||
--- a/pyanaconda/modules/payloads/source/nfs/initialization.py
|
||||
+++ b/pyanaconda/modules/payloads/source/nfs/initialization.py
|
||||
@@ -22,7 +22,7 @@
|
||||
from pyanaconda.modules.common.errors.payload import SourceSetupError
|
||||
from pyanaconda.modules.common.task import Task
|
||||
from pyanaconda.modules.payloads.source.utils import find_and_mount_iso_image, \
|
||||
- verify_valid_installtree
|
||||
+ verify_valid_repository
|
||||
from pyanaconda.payload.errors import PayloadSetupError
|
||||
from pyanaconda.payload.utils import mount, unmount
|
||||
|
||||
@@ -65,7 +65,7 @@ def run(self):
|
||||
log.debug("Using the ISO '%s' mounted at '%s'.", iso_name, self._iso_mount)
|
||||
return self._iso_mount
|
||||
|
||||
- if verify_valid_installtree(self._device_mount):
|
||||
+ if verify_valid_repository(self._device_mount):
|
||||
log.debug("Using the directory at '%s'.", self._device_mount)
|
||||
return self._device_mount
|
||||
|
||||
diff --git a/pyanaconda/modules/payloads/source/utils.py b/pyanaconda/modules/payloads/source/utils.py
|
||||
index ed9e5da49b..84cdd33ca8 100644
|
||||
--- a/pyanaconda/modules/payloads/source/utils.py
|
||||
+++ b/pyanaconda/modules/payloads/source/utils.py
|
||||
@@ -148,10 +148,10 @@ def _create_iso_path(path, iso_name):
|
||||
return path
|
||||
|
||||
|
||||
-def verify_valid_installtree(path):
|
||||
- """Check if the given path is a valid installtree repository.
|
||||
+def verify_valid_repository(path):
|
||||
+ """Check if the given path is a valid repository.
|
||||
|
||||
- :param str path: install tree path
|
||||
+ :param str path: path to the repository
|
||||
:returns: True if repository is valid false otherwise
|
||||
:rtype: bool
|
||||
"""
|
||||
diff --git a/tests/nosetests/pyanaconda_tests/module_source_base_test.py b/tests/nosetests/pyanaconda_tests/module_source_base_test.py
|
||||
index 3ba40edf4c..c9f00fa4f5 100644
|
||||
--- a/tests/nosetests/pyanaconda_tests/module_source_base_test.py
|
||||
+++ b/tests/nosetests/pyanaconda_tests/module_source_base_test.py
|
||||
@@ -26,7 +26,7 @@
|
||||
from pyanaconda.modules.payloads.source.mount_tasks import SetUpMountTask, TearDownMountTask
|
||||
from pyanaconda.modules.payloads.source.source_base import MountingSourceMixin
|
||||
from pyanaconda.modules.payloads.source.utils import find_and_mount_iso_image, \
|
||||
- verify_valid_installtree
|
||||
+ verify_valid_repository
|
||||
|
||||
mount_location = "/some/dir"
|
||||
|
||||
@@ -188,20 +188,20 @@ def find_and_mount_iso_image_fail_mount_test(self,
|
||||
|
||||
self.assertEqual(iso_name, "")
|
||||
|
||||
- def verify_valid_installtree_success_test(self):
|
||||
- """Test verify_valid_installtree functionality success."""
|
||||
+ def verify_valid_repository_success_test(self):
|
||||
+ """Test verify_valid_repository functionality success."""
|
||||
with TemporaryDirectory() as tmp:
|
||||
repodir_path = Path(tmp, "repodata")
|
||||
repodir_path.mkdir()
|
||||
repomd_path = Path(repodir_path, "repomd.xml")
|
||||
repomd_path.write_text("This is a cool repomd file!")
|
||||
|
||||
- self.assertTrue(verify_valid_installtree(tmp))
|
||||
+ self.assertTrue(verify_valid_repository(tmp))
|
||||
|
||||
- def verify_valid_installtree_failed_test(self):
|
||||
- """Test verify_valid_installtree functionality failed."""
|
||||
+ def verify_valid_repository_failed_test(self):
|
||||
+ """Test verify_valid_repository functionality failed."""
|
||||
with TemporaryDirectory() as tmp:
|
||||
repodir_path = Path(tmp, "repodata")
|
||||
repodir_path.mkdir()
|
||||
|
||||
- self.assertFalse(verify_valid_installtree(tmp))
|
||||
+ self.assertFalse(verify_valid_repository(tmp))
|
||||
diff --git a/tests/nosetests/pyanaconda_tests/module_source_harddrive_test.py b/tests/nosetests/pyanaconda_tests/module_source_harddrive_test.py
|
||||
index dff84b6d19..99be32fa1f 100644
|
||||
--- a/tests/nosetests/pyanaconda_tests/module_source_harddrive_test.py
|
||||
+++ b/tests/nosetests/pyanaconda_tests/module_source_harddrive_test.py
|
||||
@@ -211,10 +211,10 @@ def success_find_iso_test(self,
|
||||
return_value=True)
|
||||
@patch("pyanaconda.modules.payloads.source.harddrive.initialization.find_and_mount_iso_image",
|
||||
return_value="")
|
||||
- @patch("pyanaconda.modules.payloads.source.harddrive.initialization.verify_valid_installtree",
|
||||
+ @patch("pyanaconda.modules.payloads.source.harddrive.initialization.verify_valid_repository",
|
||||
return_value=True)
|
||||
def success_find_dir_test(self,
|
||||
- verify_valid_installtree_mock,
|
||||
+ verify_valid_repository_mock,
|
||||
find_and_mount_iso_image_mock,
|
||||
find_and_mount_device_mock):
|
||||
"""Hard drive source setup dir found."""
|
||||
@@ -228,7 +228,7 @@ def success_find_dir_test(self,
|
||||
find_and_mount_iso_image_mock.assert_called_once_with(
|
||||
device_mount_location + path_on_device, iso_mount_location
|
||||
)
|
||||
- verify_valid_installtree_mock.assert_called_once_with(
|
||||
+ verify_valid_repository_mock.assert_called_once_with(
|
||||
device_mount_location + path_on_device
|
||||
)
|
||||
self.assertEqual(result, SetupHardDriveResult(device_mount_location + path_on_device, ""))
|
||||
@@ -237,12 +237,12 @@ def success_find_dir_test(self,
|
||||
return_value=True)
|
||||
@patch("pyanaconda.modules.payloads.source.harddrive.initialization.find_and_mount_iso_image",
|
||||
return_value="")
|
||||
- @patch("pyanaconda.modules.payloads.source.harddrive.initialization.verify_valid_installtree",
|
||||
+ @patch("pyanaconda.modules.payloads.source.harddrive.initialization.verify_valid_repository",
|
||||
return_value=False)
|
||||
@patch("pyanaconda.modules.payloads.source.harddrive.initialization.unmount")
|
||||
def failure_to_find_anything_test(self,
|
||||
unmount_mock,
|
||||
- verify_valid_installtree_mock,
|
||||
+ verify_valid_repository_mock,
|
||||
find_and_mount_iso_image_mock,
|
||||
find_and_mount_device_mock):
|
||||
"""Hard drive source setup failure to find anything."""
|
||||
@@ -257,7 +257,7 @@ def failure_to_find_anything_test(self,
|
||||
find_and_mount_iso_image_mock.assert_called_once_with(
|
||||
device_mount_location + path_on_device, iso_mount_location
|
||||
)
|
||||
- verify_valid_installtree_mock.assert_called_once_with(
|
||||
+ verify_valid_repository_mock.assert_called_once_with(
|
||||
device_mount_location + path_on_device
|
||||
)
|
||||
unmount_mock.assert_called_once_with(
|
||||
diff --git a/tests/nosetests/pyanaconda_tests/module_source_nfs_test.py b/tests/nosetests/pyanaconda_tests/module_source_nfs_test.py
|
||||
index eb331dec10..d33796a469 100644
|
||||
--- a/tests/nosetests/pyanaconda_tests/module_source_nfs_test.py
|
||||
+++ b/tests/nosetests/pyanaconda_tests/module_source_nfs_test.py
|
||||
@@ -180,7 +180,7 @@ def success_find_iso_test(self,
|
||||
|
||||
self.assertEqual(result, iso_mount_location)
|
||||
|
||||
- @patch("pyanaconda.modules.payloads.source.nfs.initialization.verify_valid_installtree",
|
||||
+ @patch("pyanaconda.modules.payloads.source.nfs.initialization.verify_valid_repository",
|
||||
return_value=True)
|
||||
@patch("pyanaconda.modules.payloads.source.nfs.initialization.find_and_mount_iso_image",
|
||||
return_value="")
|
||||
@@ -188,7 +188,7 @@ def success_find_iso_test(self,
|
||||
def success_find_dir_test(self,
|
||||
mount_mock,
|
||||
find_and_mount_iso_image_mock,
|
||||
- verify_valid_installtree_mock):
|
||||
+ verify_valid_repository_mock):
|
||||
"""Test NFS source setup find installation tree success"""
|
||||
task = _create_setup_task()
|
||||
result = task.run()
|
||||
@@ -201,7 +201,7 @@ def success_find_dir_test(self,
|
||||
find_and_mount_iso_image_mock.assert_called_once_with(device_mount_location,
|
||||
iso_mount_location)
|
||||
|
||||
- verify_valid_installtree_mock.assert_called_once_with(device_mount_location)
|
||||
+ verify_valid_repository_mock.assert_called_once_with(device_mount_location)
|
||||
|
||||
self.assertEqual(result, device_mount_location)
|
||||
|
||||
@@ -252,7 +252,7 @@ def setup_install_source_task_mount_failure_test(self, mount_mock):
|
||||
options="nolock")
|
||||
|
||||
@patch("pyanaconda.modules.payloads.source.nfs.initialization.unmount")
|
||||
- @patch("pyanaconda.modules.payloads.source.nfs.initialization.verify_valid_installtree",
|
||||
+ @patch("pyanaconda.modules.payloads.source.nfs.initialization.verify_valid_repository",
|
||||
return_value=False)
|
||||
@patch("pyanaconda.modules.payloads.source.nfs.initialization.find_and_mount_iso_image",
|
||||
return_value="")
|
||||
@@ -260,7 +260,7 @@ def setup_install_source_task_mount_failure_test(self, mount_mock):
|
||||
def setup_install_source_task_find_anything_failure_test(self,
|
||||
mount_mock,
|
||||
find_and_mount_iso_image_mock,
|
||||
- verify_valid_installtree_mock,
|
||||
+ verify_valid_repository_mock,
|
||||
unmount_mock):
|
||||
"""Test NFS can't find anything to install from"""
|
||||
task = SetUpNFSSourceTask(device_mount_location, iso_mount_location, nfs_url)
|
||||
@@ -274,7 +274,7 @@ def setup_install_source_task_find_anything_failure_test(self,
|
||||
find_and_mount_iso_image_mock.assert_called_once_with(device_mount_location,
|
||||
iso_mount_location)
|
||||
|
||||
- verify_valid_installtree_mock.assert_called_once_with(device_mount_location)
|
||||
+ verify_valid_repository_mock.assert_called_once_with(device_mount_location)
|
||||
|
||||
unmount_mock.assert_called_once_with(
|
||||
device_mount_location
|
||||
@ -15,7 +15,7 @@ index 1abdeb2..44b573c 100755
|
||||
@@ -263,6 +263,8 @@ if __name__ == "__main__":
|
||||
from pyanaconda.flags import flags
|
||||
from pyanaconda.core.kernel import kernel_arguments
|
||||
(opts, depr) = parse_arguments(boot_cmdline=kernel_arguments)
|
||||
(opts, removed_no_inst_args) = parse_arguments(boot_cmdline=kernel_arguments)
|
||||
+ if not opts.method:
|
||||
+ opts.method = opts.stage2
|
||||
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
From e1d294331217ec7380f7f186d7a6837e72770432 Mon Sep 17 00:00:00 2001
|
||||
From: t_feng <fengtao40@huawei.com>
|
||||
Date: Fri, 19 Jun 2020 11:42:23 +0800
|
||||
Subject: [PATCH] disable-product-name-in-welcome-is-uppercase
|
||||
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/welcome.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/welcome.py b/pyanaconda/ui/gui/spokes/welcome.py
|
||||
index 3373f1d..639fdcd 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/welcome.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/welcome.py
|
||||
@@ -251,7 +251,7 @@ class WelcomeLanguageSpoke(StandaloneSpoke, LangLocaleHandler):
|
||||
languageEntry.set_placeholder_text(_(self._origStrings[languageEntry]))
|
||||
|
||||
# And of course, don't forget the underlying window.
|
||||
- self.window.set_property("distribution", distributionText().upper())
|
||||
+ self.window.set_property("distribution", distributionText())
|
||||
self.window.retranslate()
|
||||
|
||||
# Retranslate the window title text
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
From a51168ce9ab849f857efd96eae66cff5247a45a4 Mon Sep 17 00:00:00 2001
|
||||
From: t_feng <fengtao40@huawei.com>
|
||||
Date: Thu, 18 Jun 2020 17:35:01 +0800
|
||||
Subject: [PATCH] disable set passwd without confirmation
|
||||
|
||||
---
|
||||
pyanaconda/input_checking.py | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/pyanaconda/input_checking.py b/pyanaconda/input_checking.py
|
||||
index 9efbd7b..b0fd605 100644
|
||||
--- a/pyanaconda/input_checking.py
|
||||
+++ b/pyanaconda/input_checking.py
|
||||
@@ -412,6 +412,10 @@ class PasswordValidityCheck(InputCheck):
|
||||
pw_score = 4
|
||||
status_text = _(constants.SecretStatus.STRONG.value)
|
||||
|
||||
+ #disable set password without confirnation
|
||||
+ if not error_message and not check_request.password_confirmation:
|
||||
+ error_message = _(constants.SECRET_CONFIRM_ERROR_GUI[check_request.secret_type])
|
||||
+
|
||||
# the policy influences the overall success of the check
|
||||
# - score 0 & strict == True -> success = False
|
||||
# - score 0 & strict == False -> success = True
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,36 +1,36 @@
|
||||
From 6920ff7aa9c0215a032e00a5406b943737903c72 Mon Sep 17 00:00:00 2001
|
||||
From 4229601e2c53c2e002436a0132663f83a89e6e47 Mon Sep 17 00:00:00 2001
|
||||
From: t_feng <fengtao40@huawei.com>
|
||||
Date: Wed, 1 Jul 2020 18:08:35 +0800
|
||||
Subject: [PATCH] disable ssh login checkbox
|
||||
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/root_password.py | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
pyanaconda/ui/gui/spokes/root_password.py | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/root_password.py b/pyanaconda/ui/gui/spokes/root_password.py
|
||||
index 313ba0f..2af9111 100644
|
||||
index 1d19380..f2e389d 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/root_password.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/root_password.py
|
||||
@@ -72,6 +72,8 @@ class PasswordSpoke(FirstbootSpokeMixIn, NormalSpoke, GUISpokeInputCheckHandler)
|
||||
@@ -79,7 +79,8 @@ class PasswordSpoke(FirstbootSpokeMixIn, NormalSpoke, GUISpokeInputCheckHandler)
|
||||
self._password_label = self.builder.get_object("password_label")
|
||||
self._lock = self.builder.get_object("lock")
|
||||
self._root_password_ssh_login_override = self.builder.get_object("root_password_ssh_login_override")
|
||||
self._enable_root_radio = self.builder.get_object("enable_root_radio")
|
||||
self._disable_root_radio = self.builder.get_object("disable_root_radio")
|
||||
- self._root_password_ssh_login_override = self.builder.get_object("root_password_ssh_login_override")
|
||||
+ self._root_password_ssh_login_override.set_visible(False)
|
||||
+ self._root_password_ssh_login_override.set_no_show_all(True)
|
||||
self._revealer = self.builder.get_object("password_revealer")
|
||||
|
||||
# Install the password checks:
|
||||
# - Has a password been specified?
|
||||
@@ -147,9 +149,9 @@ class PasswordSpoke(FirstbootSpokeMixIn, NormalSpoke, GUISpokeInputCheckHandler)
|
||||
# we use the _refresh_running atribute to differentiate
|
||||
# it from "real" clicks
|
||||
self._lock.set_active(self._users_module.IsRootAccountLocked)
|
||||
@@ -159,9 +160,8 @@ class PasswordSpoke(FirstbootSpokeMixIn, NormalSpoke, GUISpokeInputCheckHandler)
|
||||
control.set_active(True)
|
||||
self.on_root_enabled_changed(control)
|
||||
|
||||
- self._root_password_ssh_login_override.set_active(
|
||||
- self._users_module.RootPasswordSSHLoginAllowed
|
||||
- )
|
||||
+ self._root_password_ssh_login_override.set_visible(False)
|
||||
+ self._root_password_ssh_login_override.set_no_show_all(True)
|
||||
+
|
||||
if not self._lock.get_active():
|
||||
if self.root_enabled:
|
||||
# rerun checks so that we have a correct status message, if any
|
||||
self.checker.run_checks()
|
||||
--
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
From aa819ebee288aa307dc204337228c402189fd5e5 Mon Sep 17 00:00:00 2001
|
||||
From: "Qr.Xia" <69908158+xqrustc2020@users.noreply.github.com>
|
||||
Date: Mon, 12 Oct 2020 11:04:27 +0800
|
||||
Subject: [PATCH] fix 0 storage devices selected
|
||||
|
||||
"0 storage devices selected" is printed because the format_type of sda
|
||||
is "ext4" rather than "disklabel", and disk 'sda' is filtered by
|
||||
filter_disks_by_names(partitioned_devices, selected_disks).
|
||||
Resolves: rhbz#1878661
|
||||
---
|
||||
pyanaconda/ui/gui/spokes/custom_storage.py | 6 ++----
|
||||
1 file changed, 2 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/spokes/custom_storage.py b/pyanaconda/ui/gui/spokes/custom_storage.py
|
||||
index d72e315..b89866c 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/custom_storage.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/custom_storage.py
|
||||
@@ -47,7 +47,7 @@ from pyanaconda.modules.common.structures.partitioning import PartitioningReques
|
||||
from pyanaconda.modules.common.structures.device_factory import DeviceFactoryRequest, \
|
||||
DeviceFactoryPermissions
|
||||
from pyanaconda.product import productName, productVersion
|
||||
-from pyanaconda.ui.lib.storage import reset_bootloader, create_partitioning, filter_disks_by_names
|
||||
+from pyanaconda.ui.lib.storage import reset_bootloader, create_partitioning
|
||||
from pyanaconda.core.storage import DEVICE_TYPE_UNSUPPORTED, DEVICE_TEXT_MAP, \
|
||||
MOUNTPOINT_DESCRIPTIONS, NAMED_DEVICE_TYPES, CONTAINER_DEVICE_TYPES, device_type_from_autopart, \
|
||||
PROTECTED_FORMAT_TYPES, DEVICE_TYPE_BTRFS, DEVICE_TYPE_MD, Size
|
||||
@@ -303,9 +303,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageCheckHandler):
|
||||
self._default_file_system = self._device_tree.GetDefaultFileSystem()
|
||||
|
||||
# Initialize the selected disks.
|
||||
- selected_disks = self._disk_selection.SelectedDisks
|
||||
- partitioned_devices = self._device_tree.GetPartitioned()
|
||||
- self._selected_disks = filter_disks_by_names(partitioned_devices, selected_disks)
|
||||
+ self._selected_disks = self._disk_selection.SelectedDisks
|
||||
|
||||
# Update the UI elements.
|
||||
self._do_refresh(init_expanded_pages=True)
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,44 +1,56 @@
|
||||
From 8ecae3e85d9eeedb131dbc026dcdf5bba95cdb15 Mon Sep 17 00:00:00 2001
|
||||
From cc1706cdbcabab80ab867c2a8f5a517884faa048 Mon Sep 17 00:00:00 2001
|
||||
From: t_feng <fengtao40@huawei.com>
|
||||
Date: Thu, 18 Jun 2020 17:13:47 +0800
|
||||
Subject: [PATCH] fix hostname info
|
||||
|
||||
---
|
||||
po/zh_CN.po | 6 +++---
|
||||
pyanaconda/network.py | 4 ++--
|
||||
2 files changed, 5 insertions(+), 5 deletions(-)
|
||||
po/zh_CN.po | 5 +++--
|
||||
pyanaconda/core/regexes.py | 2 +-
|
||||
pyanaconda/network.py | 3 ++-
|
||||
3 files changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/po/zh_CN.po b/po/zh_CN.po
|
||||
index 0a4d1cd..be8cefe 100644
|
||||
index e31f0b2..c02ce1e 100644
|
||||
--- a/po/zh_CN.po
|
||||
+++ b/po/zh_CN.po
|
||||
@@ -2365,11 +2365,11 @@ msgstr "本地主机名绝不能以句号\".\"结尾。"
|
||||
#: pyanaconda/network.py:119
|
||||
@@ -4090,10 +4090,11 @@ msgstr "本地主机名不能以英文句号“.”结尾。"
|
||||
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 '-'."
|
||||
+"characters and cannot start or end with '.' and '-'."
|
||||
msgstr ""
|
||||
"主机名只能包含 'a-z', 'A-Z', '0-9', '-'(英文减号), 或者 '.'(英文点号),其"
|
||||
-"中两个点号中不能为空且不能以'-'开头或结尾。"
|
||||
+"中两个点号中不能为空,必须少于64个字符且不能以'-'开头或结尾。"
|
||||
"主机名只能包含 'a-z'、'A-Z'、 '0-9'、 '-'(英文减号),或者 '.'(英文点号),"
|
||||
-"其中两个点号中不能为空且不能以 '-' 开头或结尾。"
|
||||
+"其中两个点号中不能为空,必须少于64个字符且不能以'.'和'-'开头或结尾。"
|
||||
|
||||
#: pyanaconda/network.py:465
|
||||
#: pyanaconda/network.py:457
|
||||
msgid "Status not available"
|
||||
diff --git a/pyanaconda/core/regexes.py b/pyanaconda/core/regexes.py
|
||||
index cc00702..388d1ff 100644
|
||||
--- a/pyanaconda/core/regexes.py
|
||||
+++ b/pyanaconda/core/regexes.py
|
||||
@@ -103,7 +103,7 @@ IPV4_NETMASK_WITH_ANCHORS = re.compile("^" + IPV4_NETMASK_WITHOUT_ANCHORS + "$")
|
||||
# with a period, but it can end with one.
|
||||
# This regex uses negative lookahead and lookback assertions to enforce the
|
||||
# hyphen rules and make it way more confusing
|
||||
-HOSTNAME_PATTERN_WITHOUT_ANCHORS = r'(?:(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.(?!-)[A-Za-z0-9-]{1,63}(?<!-))*\.?)'
|
||||
+HOSTNAME_PATTERN_WITHOUT_ANCHORS = r'(?:(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.(?!-)[A-Za-z0-9-]{1,63}(?<!-))*)'
|
||||
|
||||
# URL Hostname
|
||||
# This matches any hostname, IPv4 literal or properly encased IPv6 literal
|
||||
diff --git a/pyanaconda/network.py b/pyanaconda/network.py
|
||||
index f8e9b19..127a1bd 100644
|
||||
index 38fe957..c52cf1d 100644
|
||||
--- a/pyanaconda/network.py
|
||||
+++ b/pyanaconda/network.py
|
||||
@@ -118,8 +118,8 @@ def is_valid_hostname(hostname, local=False):
|
||||
if not re.match('^' + HOSTNAME_PATTERN_WITHOUT_ANCHORS + '$', hostname):
|
||||
@@ -115,7 +115,8 @@ def is_valid_hostname(hostname, local=False):
|
||||
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 '-'."))
|
||||
+ "characters and cannot start or end with '.' and '-'."))
|
||||
|
||||
return (True, "")
|
||||
|
||||
|
||||
@ -1,46 +0,0 @@
|
||||
From ad48d3ab850c9dd40908a51eae3580fcc148e171 Mon Sep 17 00:00:00 2001
|
||||
From: xqrustc2020 <69908158+xqrustc2020@users.noreply.github.com>
|
||||
Date: Tue, 29 Sep 2020 13:16:43 +0800
|
||||
Subject: [PATCH] fix remove unkown partition in sda failed
|
||||
|
||||
fix: cannot create partition when sda exists a ext4 filesystem.
|
||||
When you clicked the "-" button, only the format on sda should be
|
||||
destroyed without removing sda from the device tree, but sda
|
||||
was also destroyed. As a result, sda cannot be found during disk
|
||||
initialization and an error was reported.
|
||||
Resolves: rhbz#1878661
|
||||
---
|
||||
.../modules/storage/partitioning/interactive/utils.py | 10 ++++------
|
||||
1 file changed, 4 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/storage/partitioning/interactive/utils.py b/pyanaconda/modules/storage/partitioning/interactive/utils.py
|
||||
index b52876a..fe7bd59 100644
|
||||
--- a/pyanaconda/modules/storage/partitioning/interactive/utils.py
|
||||
+++ b/pyanaconda/modules/storage/partitioning/interactive/utils.py
|
||||
@@ -1046,8 +1046,10 @@ def _destroy_device(storage, device):
|
||||
:param device: an instance of a device
|
||||
"""
|
||||
# Remove the device.
|
||||
- if device.is_disk and device.partitioned and not device.format.supported:
|
||||
- storage.recursive_remove(device)
|
||||
+ if device.is_disk:
|
||||
+ if device.partitioned and not device.format.supported:
|
||||
+ storage.recursive_remove(device)
|
||||
+ storage.initialize_disk(device)
|
||||
elif device.direct and not device.isleaf:
|
||||
# We shouldn't call this method for with non-leaf devices
|
||||
# except for those which are also directly accessible like
|
||||
@@ -1057,10 +1059,6 @@ def _destroy_device(storage, device):
|
||||
else:
|
||||
storage.destroy_device(device)
|
||||
|
||||
- # Initialize the disk.
|
||||
- if device.is_disk:
|
||||
- storage.initialize_disk(device)
|
||||
-
|
||||
# Remove empty extended partitions.
|
||||
if getattr(device, "is_logical", False):
|
||||
storage.remove_empty_extended_partitions()
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,207 +0,0 @@
|
||||
From 0b851a3f25d6e2ac7e6d06e342d0823c206ee25a Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Slavik <vslavik@redhat.com>
|
||||
Date: Wed, 21 Apr 2021 20:00:54 +0200
|
||||
Subject: [PATCH] Another attempt at the X thing. This gives up the exception
|
||||
handler test temporarily, and solves almost everything.
|
||||
|
||||
The main problem of other solutions is that once X starts,
|
||||
it steals the screen by going to tty6. If the exception handler
|
||||
test-invoking handler is not returned back immediately,
|
||||
an "after-timeout" handler can be installed instead, which switches back to tty1.
|
||||
|
||||
With that in place, it's also safe to terminate Xorg once
|
||||
it's clear it's not coming in time. The termination will happen later,
|
||||
but that does not matter any more.
|
||||
|
||||
Finally, with the termination happening,
|
||||
it is also safe to return the crash report text handler.
|
||||
|
||||
Resolves: rhbz#1918702
|
||||
|
||||
Previous work: #3107, #3132, #3141, #3295. Thanks to @bitcoffeeiux and @poncovka.
|
||||
|
||||
The one avenue left unexplored is using the -displayfd option.
|
||||
---
|
||||
pyanaconda/core/util.py | 62 ++++++++++++++++++++++++++++++++---------
|
||||
pyanaconda/display.py | 29 +++++++++++++++++--
|
||||
2 files changed, 75 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/core/util.py b/pyanaconda/core/util.py
|
||||
index b7a1731..3013cd8 100644
|
||||
--- a/pyanaconda/core/util.py
|
||||
+++ b/pyanaconda/core/util.py
|
||||
@@ -47,7 +47,7 @@ from pyanaconda.core.constants import DRACUT_SHUTDOWN_EJECT, TRANSLATIONS_UPDATE
|
||||
IPMI_ABORTED, X_TIMEOUT, TAINT_HARDWARE_UNSUPPORTED, TAINT_SUPPORT_REMOVED, \
|
||||
WARNING_HARDWARE_UNSUPPORTED, WARNING_SUPPORT_REMOVED
|
||||
from pyanaconda.core.constants import SCREENSHOTS_DIRECTORY, SCREENSHOTS_TARGET_DIRECTORY
|
||||
-from pyanaconda.errors import RemovedModuleError, ExitError
|
||||
+from pyanaconda.errors import RemovedModuleError
|
||||
|
||||
from pyanaconda.anaconda_logging import program_log_lock
|
||||
from pyanaconda.anaconda_loggers import get_module_logger, get_program_logger
|
||||
@@ -204,6 +204,19 @@ def startProgram(argv, root='/', stdin=None, stdout=subprocess.PIPE, stderr=subp
|
||||
preexec_fn=preexec, cwd=root, env=env, **kwargs)
|
||||
|
||||
|
||||
+class X11Status:
|
||||
+ """Status of Xorg launch.
|
||||
+
|
||||
+ Values of an instance can be modified from the handler functions.
|
||||
+ """
|
||||
+ def __init__(self):
|
||||
+ self.started = False
|
||||
+ self.timed_out = False
|
||||
+
|
||||
+ def needs_waiting(self):
|
||||
+ return not (self.started or self.timed_out)
|
||||
+
|
||||
+
|
||||
def startX(argv, output_redirect=None, timeout=X_TIMEOUT):
|
||||
""" Start X and return once X is ready to accept connections.
|
||||
|
||||
@@ -217,28 +230,36 @@ def startX(argv, output_redirect=None, timeout=X_TIMEOUT):
|
||||
:param output_redirect: file or file descriptor to redirect stdout and stderr to
|
||||
:param timeout: Number of seconds to timing out.
|
||||
"""
|
||||
- # Use a list so the value can be modified from the handler function
|
||||
- x11_started = [False]
|
||||
+ x11_status = X11Status()
|
||||
|
||||
- def sigusr1_handler(num, frame):
|
||||
+ # Handle successful start before timeout
|
||||
+ def sigusr1_success_handler(num, frame):
|
||||
log.debug("X server has signalled a successful start.")
|
||||
- x11_started[0] = True
|
||||
+ x11_status.started = True
|
||||
|
||||
# Fail after, let's say a minute, in case something weird happens
|
||||
# and we don't receive SIGUSR1
|
||||
def sigalrm_handler(num, frame):
|
||||
# Check that it didn't make it under the wire
|
||||
- if x11_started[0]:
|
||||
+ if x11_status.started:
|
||||
return
|
||||
+ x11_status.timed_out = True
|
||||
log.error("Timeout trying to start %s", argv[0])
|
||||
- raise ExitError("Timeout trying to start %s" % argv[0])
|
||||
|
||||
- # preexec_fn to add the SIGUSR1 handler in the child
|
||||
+ # Handle delayed start after timeout
|
||||
+ def sigusr1_too_late_handler(num, frame):
|
||||
+ if x11_status.timed_out:
|
||||
+ log.debug("SIGUSR1 received after X server timeout. Switching back to tty1. "
|
||||
+ "SIGUSR1 now again initiates test of exception reporting.")
|
||||
+ signal.signal(signal.SIGUSR1, old_sigusr1_handler)
|
||||
+
|
||||
+ # preexec_fn to add the SIGUSR1 handler in the child we are starting
|
||||
+ # see man page XServer(1), section "signals"
|
||||
def sigusr1_preexec():
|
||||
signal.signal(signal.SIGUSR1, signal.SIG_IGN)
|
||||
|
||||
try:
|
||||
- old_sigusr1_handler = signal.signal(signal.SIGUSR1, sigusr1_handler)
|
||||
+ old_sigusr1_handler = signal.signal(signal.SIGUSR1, sigusr1_success_handler)
|
||||
old_sigalrm_handler = signal.signal(signal.SIGALRM, sigalrm_handler)
|
||||
|
||||
# Start the timer
|
||||
@@ -249,16 +270,31 @@ def startX(argv, output_redirect=None, timeout=X_TIMEOUT):
|
||||
preexec_fn=sigusr1_preexec)
|
||||
WatchProcesses.watch_process(childproc, argv[0])
|
||||
|
||||
- # Wait for SIGUSR1
|
||||
- while not x11_started[0]:
|
||||
+ # Wait for SIGUSR1 or SIGALRM
|
||||
+ while x11_status.needs_waiting():
|
||||
signal.pause()
|
||||
|
||||
finally:
|
||||
- # Put everything back where it was
|
||||
+ # Stop the timer
|
||||
signal.alarm(0)
|
||||
- signal.signal(signal.SIGUSR1, old_sigusr1_handler)
|
||||
signal.signal(signal.SIGALRM, old_sigalrm_handler)
|
||||
|
||||
+ # Handle outcome of X start attempt
|
||||
+ if x11_status.started:
|
||||
+ signal.signal(signal.SIGUSR1, old_sigusr1_handler)
|
||||
+ elif x11_status.timed_out:
|
||||
+ signal.signal(signal.SIGUSR1, sigusr1_too_late_handler)
|
||||
+ # Kill Xorg because from now on we will not use it. It will exit only after sending
|
||||
+ # the signal, but at least we don't have to track that.
|
||||
+ WatchProcesses.unwatch_process(childproc)
|
||||
+ childproc.terminate()
|
||||
+ log.debug("Exception handler test suspended to prevent accidental activation by "
|
||||
+ "delayed Xorg start. Next SIGUSR1 will be handled as delayed Xorg start.")
|
||||
+ # Raise an exception to notify the caller that things went wrong. This affects
|
||||
+ # particularly pyanaconda.display.do_startup_x11_actions(), where the window manager
|
||||
+ # is started immediately after this. The WM would just wait forever.
|
||||
+ raise TimeoutError("Timeout trying to start %s" % argv[0])
|
||||
+
|
||||
|
||||
def _run_program(argv, root='/', stdin=None, stdout=None, env_prune=None, log_output=True,
|
||||
binary_output=False, filter_stderr=False):
|
||||
diff --git a/pyanaconda/display.py b/pyanaconda/display.py
|
||||
index 8379d9c..b577eb8 100644
|
||||
--- a/pyanaconda/display.py
|
||||
+++ b/pyanaconda/display.py
|
||||
@@ -22,6 +22,7 @@
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
+import textwrap
|
||||
import pkgutil
|
||||
|
||||
from pyanaconda.core.configuration.anaconda import conf
|
||||
@@ -49,6 +50,14 @@ from pyanaconda.anaconda_loggers import get_module_logger, get_stdout_logger
|
||||
log = get_module_logger(__name__)
|
||||
stdout_log = get_stdout_logger()
|
||||
|
||||
+X_TIMEOUT_ADVICE = \
|
||||
+ "Do not load the stage2 image over a slow network link.\n" \
|
||||
+ "Wait longer for the X server startup with the inst.xtimeout=<SECONDS> boot option." \
|
||||
+ "The default is 60 seconds.\n" \
|
||||
+ "Load the stage2 image into memory with the rd.live.ram boot option to decrease access " \
|
||||
+ "time.\n" \
|
||||
+ "Enforce text mode when installing from remote media with the inst.text boot option."
|
||||
+# on RHEL also: "Use the customer portal download URL in ilo/drac devices for greater speed."
|
||||
|
||||
# Spice
|
||||
|
||||
@@ -78,7 +87,7 @@ def ask_vnc_question(anaconda, vnc_server, message):
|
||||
App.initialize()
|
||||
loop = App.get_event_loop()
|
||||
loop.set_quit_callback(tui_quit_callback)
|
||||
- spoke = AskVNCSpoke(anaconda.ksdata, message)
|
||||
+ spoke = AskVNCSpoke(anaconda.ksdata, message=message)
|
||||
ScreenHandler.schedule_screen(spoke)
|
||||
App.run()
|
||||
|
||||
@@ -314,9 +323,23 @@ def setup_display(anaconda, options):
|
||||
try:
|
||||
start_x11(xtimeout)
|
||||
do_startup_x11_actions()
|
||||
- except (OSError, RuntimeError) as e:
|
||||
+ except TimeoutError as e:
|
||||
log.warning("X startup failed: %s", e)
|
||||
- stdout_log.warning("X startup failed, falling back to text mode")
|
||||
+ print("\nX did not start in the expected time, falling back to text mode. There are "
|
||||
+ "multiple ways to avoid this issue:")
|
||||
+ wrapper = textwrap.TextWrapper(initial_indent=" * ", subsequent_indent=" ",
|
||||
+ width=os.get_terminal_size().columns - 3)
|
||||
+ for line in X_TIMEOUT_ADVICE.split("\n"):
|
||||
+ print(wrapper.fill(line))
|
||||
+ util.vtActivate(1)
|
||||
+ anaconda.display_mode = constants.DisplayModes.TUI
|
||||
+ anaconda.gui_startup_failed = True
|
||||
+ time.sleep(2)
|
||||
+
|
||||
+ except (OSError, RuntimeError) as e:
|
||||
+ log.warning("X or window manager startup failed: %s", e)
|
||||
+ print("\nX or window manager startup failed, falling back to text mode.")
|
||||
+ util.vtActivate(1)
|
||||
anaconda.display_mode = constants.DisplayModes.TUI
|
||||
anaconda.gui_startup_failed = True
|
||||
time.sleep(2)
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -22,8 +22,8 @@ index 87c9cb7..63240f7 100644
|
||||
set-option -s exit-unattached off
|
||||
set-option -g base-index 1
|
||||
@@ -25,7 +24,7 @@ set-option -g history-limit 10000
|
||||
# rhbz#1722181
|
||||
new-session -d -s anaconda -n main "LD_PRELOAD=libgomp.so.1 anaconda"
|
||||
# then re-attach to it in the tmux service run on the console tty.
|
||||
new-session -d -s anaconda -n main anaconda
|
||||
|
||||
-set-option status-right '#[fg=blue]#(echo -n "Switch tab: Alt+Tab | Help: F1 ")'
|
||||
+set-option status-right '#[fg=blue]#(echo -n "Switch tab: Alt+Tab ")'
|
||||
|
||||
@ -1,62 +0,0 @@
|
||||
From 853c4c8307c7427e5ee4fb57a2ffdcad1ce9d7f6 Mon Sep 17 00:00:00 2001
|
||||
From: t_feng <fengtao40@huawei.com>
|
||||
Date: Thu, 18 Jun 2020 22:39:12 +0800
|
||||
Subject: [PATCH] make name not force to uppercase
|
||||
|
||||
---
|
||||
pyanaconda/ui/gui/__init__.py | 4 ++--
|
||||
pyanaconda/ui/gui/hubs/__init__.py | 2 +-
|
||||
pyanaconda/ui/gui/spokes/welcome.py | 2 +-
|
||||
3 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ui/gui/__init__.py b/pyanaconda/ui/gui/__init__.py
|
||||
index 8c20423..06373d9 100644
|
||||
--- a/pyanaconda/ui/gui/__init__.py
|
||||
+++ b/pyanaconda/ui/gui/__init__.py
|
||||
@@ -839,7 +839,7 @@ class GraphicalUserInterface(UserInterface):
|
||||
self._currentAction.refresh()
|
||||
|
||||
self._currentAction.window.set_beta(not self._isFinal)
|
||||
- self._currentAction.window.set_property("distribution", self._distributionText().upper())
|
||||
+ self._currentAction.window.set_property("distribution", self._distributionText())
|
||||
|
||||
# Set some program-wide settings.
|
||||
settings = Gtk.Settings.get_default()
|
||||
@@ -1005,7 +1005,7 @@ class GraphicalUserInterface(UserInterface):
|
||||
|
||||
nextAction.initialize()
|
||||
nextAction.window.set_beta(self._currentAction.window.get_beta())
|
||||
- nextAction.window.set_property("distribution", self._distributionText().upper())
|
||||
+ nextAction.window.set_property("distribution", self._distributionText())
|
||||
|
||||
if not nextAction.showable:
|
||||
self._currentAction.window.hide()
|
||||
diff --git a/pyanaconda/ui/gui/hubs/__init__.py b/pyanaconda/ui/gui/hubs/__init__.py
|
||||
index 062e04e..a99e438 100644
|
||||
--- a/pyanaconda/ui/gui/hubs/__init__.py
|
||||
+++ b/pyanaconda/ui/gui/hubs/__init__.py
|
||||
@@ -145,7 +145,7 @@ class Hub(GUIObject, common.Hub):
|
||||
# From here on, this Spoke will always exist.
|
||||
spoke = spokeClass(self.data, self.storage, self.payload)
|
||||
spoke.window.set_beta(self.window.get_beta())
|
||||
- spoke.window.set_property("distribution", distributionText().upper())
|
||||
+ spoke.window.set_property("distribution", distributionText())
|
||||
|
||||
# If a spoke is not showable, it is unreachable in the UI. We
|
||||
# might as well get rid of it.
|
||||
diff --git a/pyanaconda/ui/gui/spokes/welcome.py b/pyanaconda/ui/gui/spokes/welcome.py
|
||||
index 4f1bfbc..3373f1d 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/welcome.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/welcome.py
|
||||
@@ -241,7 +241,7 @@ class WelcomeLanguageSpoke(StandaloneSpoke, LangLocaleHandler):
|
||||
welcomeLabel = self.builder.get_object("welcomeLabel")
|
||||
|
||||
welcomeLabel.set_text(_("WELCOME TO %(name)s %(version)s.") %
|
||||
- {"name" : productName.upper(), "version" : productVersion}) # pylint: disable=no-member
|
||||
+ {"name" : productName, "version" : productVersion}) # pylint: disable=no-member
|
||||
|
||||
# Retranslate the language (filtering) entry's placeholder text
|
||||
languageEntry = self.builder.get_object("languageEntry")
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
From aa21df647d18390124379026dbaf99741d336875 Mon Sep 17 00:00:00 2001
|
||||
From: t_feng <fengtao40@huawei.com>
|
||||
Date: Fri, 19 Jun 2020 10:43:24 +0800
|
||||
Subject: [PATCH] modify arguments parsing
|
||||
|
||||
---
|
||||
pyanaconda/argument_parsing.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pyanaconda/argument_parsing.py b/pyanaconda/argument_parsing.py
|
||||
index 6b2f40f..ce29587 100644
|
||||
--- a/pyanaconda/argument_parsing.py
|
||||
+++ b/pyanaconda/argument_parsing.py
|
||||
@@ -592,7 +592,7 @@ def getArgumentParser(version_string, boot_cmdline=None):
|
||||
|
||||
# some defaults change based on cmdline flags
|
||||
if boot_cmdline is not None:
|
||||
- if "console" in boot_cmdline:
|
||||
+ if "console" in boot_cmdline and "inst.text" in boot_cmdline:
|
||||
ap.set_defaults(display_mode=DisplayModes.TUI)
|
||||
|
||||
return ap
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,55 +0,0 @@
|
||||
From 59a4b9b04388e327e135f3ab9893698e2b3f5a5d Mon Sep 17 00:00:00 2001
|
||||
From: t_feng <fengtao40@huawei.com>
|
||||
Date: Fri, 19 Jun 2020 11:44:31 +0800
|
||||
Subject: [PATCH] modify default timezone
|
||||
|
||||
---
|
||||
pyanaconda/modules/timezone/installation.py | 4 ++--
|
||||
pyanaconda/modules/timezone/timezone.py | 2 +-
|
||||
pyanaconda/ui/gui/spokes/datetime_spoke.py | 2 +-
|
||||
3 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/timezone/installation.py b/pyanaconda/modules/timezone/installation.py
|
||||
index 6383df1..9c6ae40 100644
|
||||
--- a/pyanaconda/modules/timezone/installation.py
|
||||
+++ b/pyanaconda/modules/timezone/installation.py
|
||||
@@ -63,8 +63,8 @@ class ConfigureTimezoneTask(Task):
|
||||
if not is_valid_timezone(self._timezone):
|
||||
# this should never happen, but for pity's sake
|
||||
log.warning("Timezone %s set in kickstart is not valid, "
|
||||
- "falling back to default (America/New_York).", self._timezone)
|
||||
- self._timezone = "America/New_York"
|
||||
+ "falling back to default (Asia/Shanghai).", self._timezone)
|
||||
+ self._timezone = "Asia/Shanghai"
|
||||
|
||||
def _make_timezone_symlink(self):
|
||||
"""Create the symlink that actually defines timezone."""
|
||||
diff --git a/pyanaconda/modules/timezone/timezone.py b/pyanaconda/modules/timezone/timezone.py
|
||||
index 0678072..db1cd18 100644
|
||||
--- a/pyanaconda/modules/timezone/timezone.py
|
||||
+++ b/pyanaconda/modules/timezone/timezone.py
|
||||
@@ -40,7 +40,7 @@ class TimezoneService(KickstartService):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.timezone_changed = Signal()
|
||||
- self._timezone = "America/New_York"
|
||||
+ self._timezone = "Asia/Shanghai"
|
||||
|
||||
self.is_utc_changed = Signal()
|
||||
self._is_utc = False
|
||||
diff --git a/pyanaconda/ui/gui/spokes/datetime_spoke.py b/pyanaconda/ui/gui/spokes/datetime_spoke.py
|
||||
index 00b1bd9..f01d245 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/datetime_spoke.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/datetime_spoke.py
|
||||
@@ -65,7 +65,7 @@ SERVER_POOL = 1
|
||||
SERVER_WORKING = 2
|
||||
SERVER_USE = 3
|
||||
|
||||
-DEFAULT_TZ = "America/New_York"
|
||||
+DEFAULT_TZ = "Asia/Shanghai"
|
||||
|
||||
SPLIT_NUMBER_SUFFIX_RE = re.compile(r'([^0-9]*)([-+])([0-9]+)')
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
From 1999c1bd693ee187cc699fd1f1d4ac77086373b9 Mon Sep 17 00:00:00 2001
|
||||
From ae056f86eca56a76ae9736d7f199d73548a7574b Mon Sep 17 00:00:00 2001
|
||||
From: t_feng <fengtao40@huawei.com>
|
||||
Date: Fri, 19 Jun 2020 09:26:00 +0800
|
||||
Date: Mon, 7 Nov 2022 20:03:39 +0800
|
||||
Subject: [PATCH] modify interface is extended in Chinese mode
|
||||
|
||||
---
|
||||
@ -8,14 +8,14 @@ Subject: [PATCH] modify interface is extended in Chinese mode
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/po/zh_CN.po b/po/zh_CN.po
|
||||
index be8cefe..7ee5511 100644
|
||||
index 8f48aad..18b0925 100644
|
||||
--- a/po/zh_CN.po
|
||||
+++ b/po/zh_CN.po
|
||||
@@ -6429,7 +6429,7 @@ msgstr "搜索方式(_B):"
|
||||
@@ -4433,7 +4433,7 @@ msgstr "搜索方式(_B):"
|
||||
|
||||
#: pyanaconda/ui/gui/spokes/advanced_storage.glade:153
|
||||
msgid "Port / Target / LUN #"
|
||||
-msgstr "端口 / 目标 / 逻辑单位数标示符 (LUN #) "
|
||||
-msgstr "端口 / 目标 / 逻辑单位数标示符 (LUN #)"
|
||||
+msgstr "端口 / 目标 / LUN # "
|
||||
|
||||
#: pyanaconda/ui/gui/spokes/advanced_storage.glade:154
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
From 343751258b3a4b3e21cf52add5a9ddf600065835 Mon Sep 17 00:00:00 2001
|
||||
From: t_feng <fengtao40@huawei.com>
|
||||
Date: Fri, 19 Jun 2020 11:48:25 +0800
|
||||
Subject: [PATCH] modify network hostname dot illegal
|
||||
|
||||
---
|
||||
pyanaconda/core/regexes.py | 2 +-
|
||||
pyanaconda/network.py | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/core/regexes.py b/pyanaconda/core/regexes.py
|
||||
index 63ab668..f86e403 100644
|
||||
--- a/pyanaconda/core/regexes.py
|
||||
+++ b/pyanaconda/core/regexes.py
|
||||
@@ -103,7 +103,7 @@ IPV4_NETMASK_WITH_ANCHORS = re.compile("^" + IPV4_NETMASK_WITHOUT_ANCHORS + "$")
|
||||
# with a period, but it can end with one.
|
||||
# This regex uses negative lookahead and lookback assertions to enforce the
|
||||
# hyphen rules and make it way more confusing
|
||||
-HOSTNAME_PATTERN_WITHOUT_ANCHORS = r'(?:(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.(?!-)[A-Za-z0-9-]{1,63}(?<!-))*\.?)'
|
||||
+HOSTNAME_PATTERN_WITHOUT_ANCHORS = r'(?:(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.(?!-)[A-Za-z0-9-]{1,63}(?<!-))*)'
|
||||
|
||||
# URL Hostname
|
||||
# This matches any hostname, IPv4 literal or properly encased IPv6 literal
|
||||
diff --git a/pyanaconda/network.py b/pyanaconda/network.py
|
||||
index 127a1bd..30cf2af 100644
|
||||
--- a/pyanaconda/network.py
|
||||
+++ b/pyanaconda/network.py
|
||||
@@ -119,7 +119,7 @@ def is_valid_hostname(hostname, local=False):
|
||||
return (False, _("Host names can only contain the characters 'a-z', "
|
||||
"'A-Z', '0-9', '-', or '.', parts between periods "
|
||||
"must contain something being 63 or fewer "
|
||||
- "characters and cannot start or end with '-'."))
|
||||
+ "characters and cannot start or end with '.' and '-'."))
|
||||
|
||||
return (True, "")
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,18 +1,60 @@
|
||||
diff -Nur anaconda-33.19.org/pyanaconda/ui/gui/spokes/datetime_spoke.glade anaconda-33.19/pyanaconda/ui/gui/spokes/datetime_spoke.glade
|
||||
--- anaconda-33.19.org/pyanaconda/ui/gui/spokes/datetime_spoke.glade 2021-08-07 16:25:21.547621965 +0800
|
||||
+++ anaconda-33.19/pyanaconda/ui/gui/spokes/datetime_spoke.glade 2021-08-07 16:26:20.137758256 +0800
|
||||
From 303b072992542dfa9a7e2b2a9dc99120564a3f07 Mon Sep 17 00:00:00 2001
|
||||
From: sun_hai_10 <sunhai10@huawei.com>
|
||||
Date: Mon, 7 Nov 2022 14:23:04 +0800
|
||||
Subject: [PATCH] modify timezone and delete datezone map
|
||||
|
||||
---
|
||||
pyanaconda/modules/timezone/installation.py | 4 +-
|
||||
pyanaconda/modules/timezone/timezone.py | 2 +-
|
||||
pyanaconda/ui/gui/spokes/datetime_spoke.glade | 14 -------
|
||||
pyanaconda/ui/gui/spokes/datetime_spoke.py | 38 +++----------------
|
||||
4 files changed, 8 insertions(+), 50 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/timezone/installation.py b/pyanaconda/modules/timezone/installation.py
|
||||
index 08e24c0..f11874f 100644
|
||||
--- a/pyanaconda/modules/timezone/installation.py
|
||||
+++ b/pyanaconda/modules/timezone/installation.py
|
||||
@@ -63,8 +63,8 @@ class ConfigureTimezoneTask(Task):
|
||||
if not is_valid_timezone(self._timezone):
|
||||
# this should never happen, but for pity's sake
|
||||
log.warning("Timezone %s set in kickstart is not valid, "
|
||||
- "falling back to default (America/New_York).", self._timezone)
|
||||
- self._timezone = "America/New_York"
|
||||
+ "falling back to default (Asia/Shanghai).", self._timezone)
|
||||
+ self._timezone = "Asia/Shanghai"
|
||||
|
||||
def _make_timezone_symlink(self):
|
||||
"""Create the symlink that actually defines timezone."""
|
||||
diff --git a/pyanaconda/modules/timezone/timezone.py b/pyanaconda/modules/timezone/timezone.py
|
||||
index b5d5f7b..2a328a3 100644
|
||||
--- a/pyanaconda/modules/timezone/timezone.py
|
||||
+++ b/pyanaconda/modules/timezone/timezone.py
|
||||
@@ -44,7 +44,7 @@ class TimezoneService(KickstartService):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.timezone_changed = Signal()
|
||||
- self._timezone = "America/New_York"
|
||||
+ self._timezone = "Asia/Shanghai"
|
||||
|
||||
self.is_utc_changed = Signal()
|
||||
self._is_utc = False
|
||||
diff --git a/pyanaconda/ui/gui/spokes/datetime_spoke.glade b/pyanaconda/ui/gui/spokes/datetime_spoke.glade
|
||||
index 188f93b..aa468d9 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/datetime_spoke.glade
|
||||
+++ b/pyanaconda/ui/gui/spokes/datetime_spoke.glade
|
||||
@@ -3,7 +3,6 @@
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.12"/>
|
||||
<requires lib="AnacondaWidgets" version="1.0"/>
|
||||
- <requires lib="TimezoneMap" version="0.4"/>
|
||||
<object class="GtkImage" id="addImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
@@ -548,19 +547,6 @@
|
||||
<object class="GtkListStore" id="cities">
|
||||
<columns>
|
||||
<!-- column-name name -->
|
||||
@@ -314,19 +313,6 @@
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
- <child>
|
||||
- <object class="CcTimezoneMap" id="tzmap">
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
@ -25,14 +67,14 @@ diff -Nur anaconda-33.19.org/pyanaconda/ui/gui/spokes/datetime_spoke.glade anaco
|
||||
- <property name="position">1</property>
|
||||
- </packing>
|
||||
- </child>
|
||||
- <child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="footerAlignment">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
diff -Nur anaconda-33.19.org/pyanaconda/ui/gui/spokes/datetime_spoke.py anaconda-33.19/pyanaconda/ui/gui/spokes/datetime_spoke.py
|
||||
--- anaconda-33.19.org/pyanaconda/ui/gui/spokes/datetime_spoke.py 2021-08-07 16:25:21.547621965 +0800
|
||||
+++ anaconda-33.19/pyanaconda/ui/gui/spokes/datetime_spoke.py 2021-08-07 16:30:03.958279259 +0800
|
||||
@@ -53,9 +53,8 @@
|
||||
diff --git a/pyanaconda/ui/gui/spokes/datetime_spoke.py b/pyanaconda/ui/gui/spokes/datetime_spoke.py
|
||||
index b21bbc3..c8416b4 100644
|
||||
--- a/pyanaconda/ui/gui/spokes/datetime_spoke.py
|
||||
+++ b/pyanaconda/ui/gui/spokes/datetime_spoke.py
|
||||
@@ -50,15 +50,14 @@ from pyanaconda.threading import threadMgr, AnacondaThread
|
||||
import gi
|
||||
gi.require_version("Gdk", "3.0")
|
||||
gi.require_version("Gtk", "3.0")
|
||||
@ -43,7 +85,14 @@ diff -Nur anaconda-33.19.org/pyanaconda/ui/gui/spokes/datetime_spoke.py anaconda
|
||||
|
||||
log = get_module_logger(__name__)
|
||||
|
||||
@@ -377,11 +376,6 @@
|
||||
__all__ = ["DatetimeSpoke"]
|
||||
|
||||
-DEFAULT_TZ = "America/New_York"
|
||||
+DEFAULT_TZ = "Asia/Shanghai"
|
||||
|
||||
SPLIT_NUMBER_SUFFIX_RE = re.compile(r'([^0-9]*)([-+])([0-9]+)')
|
||||
|
||||
@@ -168,11 +167,6 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
|
||||
icon = "preferences-system-time-symbolic"
|
||||
title = CN_("GUI|Spoke", "_Time & Date")
|
||||
|
||||
@ -52,10 +101,10 @@ diff -Nur anaconda-33.19.org/pyanaconda/ui/gui/spokes/datetime_spoke.py anaconda
|
||||
- _hack = TimezoneMap.TimezoneMap()
|
||||
- del(_hack)
|
||||
-
|
||||
def __init__(self, *args):
|
||||
NormalSpoke.__init__(self, *args)
|
||||
|
||||
@@ -407,7 +401,6 @@
|
||||
@staticmethod
|
||||
def get_screen_id():
|
||||
"""Return a unique id of this UI screen."""
|
||||
@@ -211,7 +205,6 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
|
||||
self._yearsStore = self.builder.get_object("years")
|
||||
self._regionsStore = self.builder.get_object("regions")
|
||||
self._citiesStore = self.builder.get_object("cities")
|
||||
@ -63,7 +112,7 @@ diff -Nur anaconda-33.19.org/pyanaconda/ui/gui/spokes/datetime_spoke.py anaconda
|
||||
self._dateBox = self.builder.get_object("dateBox")
|
||||
|
||||
# we need to know it the new value is the same as previous or not
|
||||
@@ -530,10 +523,6 @@
|
||||
@@ -334,10 +327,6 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
|
||||
else:
|
||||
return _("Invalid timezone")
|
||||
else:
|
||||
@ -74,7 +123,7 @@ diff -Nur anaconda-33.19.org/pyanaconda/ui/gui/spokes/datetime_spoke.py anaconda
|
||||
return _("Nothing selected")
|
||||
|
||||
def apply(self):
|
||||
@@ -585,7 +574,6 @@
|
||||
@@ -389,7 +378,6 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
|
||||
kickstart_timezone = self._timezone_module.Timezone
|
||||
|
||||
if is_valid_timezone(kickstart_timezone):
|
||||
@ -82,17 +131,17 @@ diff -Nur anaconda-33.19.org/pyanaconda/ui/gui/spokes/datetime_spoke.py anaconda
|
||||
time.tzset()
|
||||
|
||||
self._update_datetime()
|
||||
@@ -960,7 +948,6 @@
|
||||
@@ -766,7 +754,6 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
|
||||
if region == "Etc":
|
||||
# Etc timezones cannot be displayed on the map, so let's reset the
|
||||
# location and manually set a highlight with no location pin.
|
||||
- self._tzmap.clear_location()
|
||||
if city in ("GMT", "UTC"):
|
||||
# Some time zones are just the same default.
|
||||
if city in ("GMT", "UTC", "UCT", "Greenwich", "Universal", "Zulu"):
|
||||
offset = 0.0
|
||||
# The tzdb data uses POSIX-style signs for the GMT zones, which is
|
||||
@@ -971,13 +958,14 @@
|
||||
# Take the part after "GMT"
|
||||
offset = -float(city[3:])
|
||||
@@ -780,13 +767,14 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
|
||||
else:
|
||||
log.warning("Unknown time zone selected in GUI: Etc/%s", city)
|
||||
|
||||
- self._tzmap.set_selected_offset(offset)
|
||||
time.tzset()
|
||||
@ -107,7 +156,7 @@ diff -Nur anaconda-33.19.org/pyanaconda/ui/gui/spokes/datetime_spoke.py anaconda
|
||||
# update "old" values
|
||||
self._old_city = city
|
||||
|
||||
@@ -1027,22 +1015,6 @@
|
||||
@@ -836,22 +824,6 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
|
||||
self._stop_and_maybe_start_time_updating(interval=5)
|
||||
self._daysFilter.refilter()
|
||||
|
||||
@ -130,3 +179,6 @@ diff -Nur anaconda-33.19.org/pyanaconda/ui/gui/spokes/datetime_spoke.py anaconda
|
||||
def on_timeformat_changed(self, button24h, *args):
|
||||
hours = int(self._hoursLabel.get_text())
|
||||
amPm = self._amPmLabel.get_text()
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,119 +0,0 @@
|
||||
From 554be1cfd3d09035e0370f1efc46d3fc40f8496d Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Fri, 3 Jul 2020 11:11:46 +0200
|
||||
Subject: [PATCH] Create a new DBus structure for time sources
|
||||
|
||||
Use the class TimeSourceData to represent a time source.
|
||||
---
|
||||
pyanaconda/core/constants.py | 4 +
|
||||
.../modules/common/structures/timezone.py | 84 +++++++++++++++++++
|
||||
2 files changed, 88 insertions(+)
|
||||
create mode 100644 pyanaconda/modules/common/structures/timezone.py
|
||||
|
||||
diff --git a/pyanaconda/core/constants.py b/pyanaconda/core/constants.py
|
||||
index 536529f4e0..5124f05b7f 100644
|
||||
--- a/pyanaconda/core/constants.py
|
||||
+++ b/pyanaconda/core/constants.py
|
||||
@@ -306,6 +306,10 @@ class SecretStatus(Enum):
|
||||
# Window title text
|
||||
WINDOW_TITLE_TEXT = N_("Anaconda Installer")
|
||||
|
||||
+# Types of time sources.
|
||||
+TIME_SOURCE_SERVER = "SERVER"
|
||||
+TIME_SOURCE_POOL = "POOL"
|
||||
+
|
||||
# NTP server checking
|
||||
NTP_SERVER_OK = 0
|
||||
NTP_SERVER_NOK = 1
|
||||
diff --git a/pyanaconda/modules/common/structures/timezone.py b/pyanaconda/modules/common/structures/timezone.py
|
||||
new file mode 100644
|
||||
index 0000000000..d18234f681
|
||||
--- /dev/null
|
||||
+++ b/pyanaconda/modules/common/structures/timezone.py
|
||||
@@ -0,0 +1,84 @@
|
||||
+#
|
||||
+# DBus structures for the timezone data.
|
||||
+#
|
||||
+# Copyright (C) 2020 Red Hat, Inc. All rights reserved.
|
||||
+#
|
||||
+# This program is free software; you can redistribute it and/or modify
|
||||
+# it under the terms of the GNU General Public License as published by
|
||||
+# the Free Software Foundation; either version 2 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+#
|
||||
+from dasbus.structure import DBusData
|
||||
+from dasbus.typing import * # pylint: disable=wildcard-import
|
||||
+
|
||||
+from pyanaconda.core.constants import TIME_SOURCE_SERVER
|
||||
+
|
||||
+__all__ = ["TimeSourceData"]
|
||||
+
|
||||
+
|
||||
+class TimeSourceData(DBusData):
|
||||
+ """Data for a time source."""
|
||||
+
|
||||
+ def __init__(self):
|
||||
+ self._type = TIME_SOURCE_SERVER
|
||||
+ self._hostname = ""
|
||||
+ self._options = []
|
||||
+
|
||||
+ @property
|
||||
+ def type(self) -> Str:
|
||||
+ """Type of the time source.
|
||||
+
|
||||
+ Supported values:
|
||||
+
|
||||
+ SERVER A single NTP server
|
||||
+ POOL A pool of NTP servers
|
||||
+
|
||||
+ :return: a type of the time source
|
||||
+ """
|
||||
+ return self._type
|
||||
+
|
||||
+ @type.setter
|
||||
+ def type(self, value: Str):
|
||||
+ self._type = value
|
||||
+
|
||||
+ @property
|
||||
+ def hostname(self) -> Str:
|
||||
+ """Name of the time server.
|
||||
+
|
||||
+ For example:
|
||||
+
|
||||
+ ntp.cesnet.cz
|
||||
+
|
||||
+ :return: a host name
|
||||
+ """
|
||||
+ return self._hostname
|
||||
+
|
||||
+ @hostname.setter
|
||||
+ def hostname(self, value: Str):
|
||||
+ self._hostname = value
|
||||
+
|
||||
+ @property
|
||||
+ def options(self) -> List[Str]:
|
||||
+ """Options of the time source.
|
||||
+
|
||||
+ For example:
|
||||
+
|
||||
+ nts, ntsport 1234, iburst
|
||||
+
|
||||
+ See ``man chrony.conf``.
|
||||
+
|
||||
+ :return: a list of options
|
||||
+ """
|
||||
+ return self._options
|
||||
+
|
||||
+ @options.setter
|
||||
+ def options(self, value):
|
||||
+ self._options = value
|
||||
--
|
||||
2.23.0
|
||||
@ -1,290 +0,0 @@
|
||||
From a645a1b8d17310533ef2d9232855c1852558e2b8 Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Fri, 3 Jul 2020 12:04:04 +0200
|
||||
Subject: [PATCH] Use the structure for time sources in ntp.py
|
||||
|
||||
Modify ntp.py to work with TimeSourceData instead of strings and clean up
|
||||
its functions a little.
|
||||
---
|
||||
pyanaconda/ntp.py | 174 +++++++++++++++++++---------------------------
|
||||
1 file changed, 73 insertions(+), 101 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/ntp.py b/pyanaconda/ntp.py
|
||||
index 16eece65e4..1b74ac9433 100644
|
||||
--- a/pyanaconda/ntp.py
|
||||
+++ b/pyanaconda/ntp.py
|
||||
@@ -31,6 +31,7 @@
|
||||
from pyanaconda import isys
|
||||
from pyanaconda.threading import threadMgr, AnacondaThread
|
||||
from pyanaconda.core.constants import THREAD_SYNC_TIME_BASENAME
|
||||
+from pyanaconda.modules.common.structures.timezone import TimeSourceData
|
||||
|
||||
NTP_CONFIG_FILE = "/etc/chrony.conf"
|
||||
|
||||
@@ -47,21 +48,18 @@ class NTPconfigError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
-def ntp_server_working(server):
|
||||
- """
|
||||
- Tries to do an NTP request to the $server (timeout may take some time).
|
||||
+def ntp_server_working(server_hostname):
|
||||
+ """Tries to do an NTP request to the server (timeout may take some time).
|
||||
|
||||
- :param server: hostname or IP address of an NTP server
|
||||
- :type server: string
|
||||
+ :param server_hostname: a host name or an IP address of an NTP server
|
||||
+ :type server_hostname: string
|
||||
:return: True if the given server is reachable and working, False otherwise
|
||||
:rtype: bool
|
||||
-
|
||||
"""
|
||||
-
|
||||
client = ntplib.NTPClient()
|
||||
|
||||
try:
|
||||
- client.request(server)
|
||||
+ client.request(server_hostname)
|
||||
except ntplib.NTPException:
|
||||
return False
|
||||
# address related error
|
||||
@@ -75,118 +73,89 @@ def ntp_server_working(server):
|
||||
return True
|
||||
|
||||
|
||||
-def pools_servers_to_internal(pools, servers):
|
||||
- ret = []
|
||||
- for pool in pools:
|
||||
- ret.extend(SERVERS_PER_POOL * [pool])
|
||||
- ret.extend(servers)
|
||||
-
|
||||
- return ret
|
||||
-
|
||||
-
|
||||
-def internal_to_pools_and_servers(pools_servers):
|
||||
- server_nums = dict()
|
||||
- pools = []
|
||||
- servers = []
|
||||
-
|
||||
- for item in pools_servers:
|
||||
- server_nums[item] = server_nums.get(item, 0) + 1
|
||||
-
|
||||
- for item in server_nums.keys():
|
||||
- if server_nums[item] >= SERVERS_PER_POOL:
|
||||
- pools.extend((server_nums[item] // SERVERS_PER_POOL) * [item])
|
||||
- servers.extend((server_nums[item] % SERVERS_PER_POOL) * [item])
|
||||
- else:
|
||||
- servers.extend(server_nums[item] * [item])
|
||||
+def get_servers_from_config(conf_file_path=NTP_CONFIG_FILE):
|
||||
+ """Get NTP servers from a configuration file.
|
||||
|
||||
- return (pools, servers)
|
||||
-
|
||||
-
|
||||
-def get_servers_from_config(conf_file_path=NTP_CONFIG_FILE,
|
||||
- srv_regexp=SRV_LINE_REGEXP):
|
||||
- """
|
||||
Goes through the chronyd's configuration file looking for lines starting
|
||||
with 'server'.
|
||||
|
||||
+ :param conf_file_path: a path to the chronyd's configuration file
|
||||
:return: servers found in the chronyd's configuration
|
||||
- :rtype: list
|
||||
-
|
||||
+ :rtype: a list of TimeSourceData instances
|
||||
"""
|
||||
-
|
||||
- pools = list()
|
||||
- servers = list()
|
||||
+ servers = []
|
||||
|
||||
try:
|
||||
with open(conf_file_path, "r") as conf_file:
|
||||
for line in conf_file:
|
||||
- match = srv_regexp.match(line)
|
||||
- if match:
|
||||
- if match.group(1) == "pool":
|
||||
- pools.append(match.group(2))
|
||||
- else:
|
||||
- servers.append(match.group(2))
|
||||
+ match = SRV_LINE_REGEXP.match(line)
|
||||
+
|
||||
+ if not match:
|
||||
+ continue
|
||||
+
|
||||
+ server = TimeSourceData()
|
||||
+ server.type = match.group(1).upper()
|
||||
+ server.hostname = match.group(2)
|
||||
+ server.options = ["iburst"]
|
||||
+ servers.append(server)
|
||||
|
||||
except IOError as ioerr:
|
||||
- msg = "Cannot open config file %s for reading (%s)" % (conf_file_path,
|
||||
- ioerr.strerror)
|
||||
- raise NTPconfigError(msg)
|
||||
+ msg = "Cannot open config file {} for reading ({})."
|
||||
+ raise NTPconfigError(msg.format(conf_file_path, ioerr.strerror))
|
||||
|
||||
- return (pools, servers)
|
||||
+ return servers
|
||||
|
||||
|
||||
-def save_servers_to_config(pools, servers, conf_file_path=NTP_CONFIG_FILE,
|
||||
- srv_regexp=SRV_LINE_REGEXP, out_file_path=None):
|
||||
- """
|
||||
+def save_servers_to_config(servers, conf_file_path=NTP_CONFIG_FILE, out_file_path=None):
|
||||
+ """Save NTP servers to a configuration file.
|
||||
+
|
||||
Replaces the pools and servers defined in the chronyd's configuration file
|
||||
with the given ones. If the out_file is not None, then it is used for the
|
||||
resulting config.
|
||||
|
||||
- :type pools: iterable
|
||||
- :type servers: iterable
|
||||
- :param out_file_path: path to the file used for the resulting config
|
||||
-
|
||||
+ :param servers: a list of NTP servers and pools
|
||||
+ :type servers: a list of TimeSourceData instances
|
||||
+ :param conf_file_path: a path to the chronyd's configuration file
|
||||
+ :param out_file_path: a path to the file used for the resulting config
|
||||
"""
|
||||
+ temp_path = None
|
||||
|
||||
try:
|
||||
old_conf_file = open(conf_file_path, "r")
|
||||
-
|
||||
except IOError as ioerr:
|
||||
- msg = "Cannot open config file %s for reading (%s)" % (conf_file_path,
|
||||
- ioerr.strerror)
|
||||
- raise NTPconfigError(msg)
|
||||
+ msg = "Cannot open config file {} for reading ({})."
|
||||
+ raise NTPconfigError(msg.format(conf_file_path, ioerr.strerror))
|
||||
|
||||
- try:
|
||||
- if out_file_path:
|
||||
+ if out_file_path:
|
||||
+ try:
|
||||
new_conf_file = open(out_file_path, "w")
|
||||
- else:
|
||||
- (fildes, temp_path) = tempfile.mkstemp()
|
||||
- new_conf_file = os.fdopen(fildes, "w")
|
||||
-
|
||||
- except IOError as ioerr:
|
||||
- if out_file_path:
|
||||
- msg = "Cannot open new config file %s "\
|
||||
- "for writing (%s)" % (out_file_path, ioerr.strerror)
|
||||
- else:
|
||||
- msg = "Cannot open temporary file %s "\
|
||||
- "for writing (%s)" % (temp_path, ioerr.strerror)
|
||||
-
|
||||
- raise NTPconfigError(msg)
|
||||
+ except IOError as ioerr:
|
||||
+ msg = "Cannot open new config file {} for writing ({})."
|
||||
+ raise NTPconfigError(msg.format(out_file_path, ioerr.strerror))
|
||||
+ else:
|
||||
+ try:
|
||||
+ (fields, temp_path) = tempfile.mkstemp()
|
||||
+ new_conf_file = os.fdopen(fields, "w")
|
||||
+ except IOError as ioerr:
|
||||
+ msg = "Cannot open temporary file {} for writing ({})."
|
||||
+ raise NTPconfigError(msg.format(temp_path, ioerr.strerror))
|
||||
|
||||
heading = "# These servers were defined in the installation:\n"
|
||||
|
||||
- #write info about the origin of the following lines
|
||||
+ # write info about the origin of the following lines
|
||||
new_conf_file.write(heading)
|
||||
|
||||
- #write new servers and pools
|
||||
- for pool in pools:
|
||||
- new_conf_file.write("pool " + pool + " iburst\n")
|
||||
-
|
||||
+ # write new servers and pools
|
||||
for server in servers:
|
||||
- new_conf_file.write("server " + server + " iburst\n")
|
||||
+ args = [server.type.lower(), server.hostname] + server.options
|
||||
+ line = " ".join(args) + "\n"
|
||||
+ new_conf_file.write(line)
|
||||
|
||||
- #copy non-server lines from the old config and skip our heading
|
||||
+ new_conf_file.write("\n")
|
||||
+
|
||||
+ # copy non-server lines from the old config and skip our heading
|
||||
for line in old_conf_file:
|
||||
- if not srv_regexp.match(line) and line != heading:
|
||||
+ if not SRV_LINE_REGEXP.match(line) and line != heading:
|
||||
new_conf_file.write(line)
|
||||
|
||||
old_conf_file.close()
|
||||
@@ -199,28 +168,27 @@ def save_servers_to_config(pools, servers, conf_file_path=NTP_CONFIG_FILE,
|
||||
os.unlink(temp_path)
|
||||
|
||||
except OSError as oserr:
|
||||
- msg = "Cannot replace the old config with "\
|
||||
- "the new one (%s)" % (oserr.strerror)
|
||||
+ msg = "Cannot replace the old config with the new one ({})."
|
||||
+ raise NTPconfigError(msg.format(oserr.strerror))
|
||||
|
||||
- raise NTPconfigError(msg)
|
||||
|
||||
+def _one_time_sync(server, callback=None):
|
||||
+ """Synchronize the system time with a given NTP server.
|
||||
|
||||
-def one_time_sync(server, callback=None):
|
||||
- """
|
||||
Synchronize the system time with a given NTP server. Note that this
|
||||
function is blocking and will not return until the time gets synced or
|
||||
querying server fails (may take some time before timeouting).
|
||||
|
||||
- :param server: NTP server
|
||||
+ :param server: an NTP server
|
||||
+ :type server: an instance of TimeSourceData
|
||||
:param callback: callback function to run after sync or failure
|
||||
:type callback: a function taking one boolean argument (success)
|
||||
:return: True if the sync was successful, False otherwise
|
||||
-
|
||||
"""
|
||||
|
||||
client = ntplib.NTPClient()
|
||||
try:
|
||||
- results = client.request(server)
|
||||
+ results = client.request(server.hostname)
|
||||
isys.set_system_time(int(results.tx_time))
|
||||
success = True
|
||||
except ntplib.NTPException:
|
||||
@@ -235,22 +203,26 @@ def one_time_sync(server, callback=None):
|
||||
|
||||
|
||||
def one_time_sync_async(server, callback=None):
|
||||
- """
|
||||
+ """Asynchronously synchronize the system time with a given NTP server.
|
||||
+
|
||||
Asynchronously synchronize the system time with a given NTP server. This
|
||||
function is non-blocking it starts a new thread for synchronization and
|
||||
returns. Use callback argument to specify the function called when the
|
||||
new thread finishes if needed.
|
||||
|
||||
- :param server: NTP server
|
||||
+ :param server: an NTP server
|
||||
+ :type server: an instance of TimeSourceData
|
||||
:param callback: callback function to run after sync or failure
|
||||
:type callback: a function taking one boolean argument (success)
|
||||
-
|
||||
"""
|
||||
+ thread_name = "%s_%s" % (THREAD_SYNC_TIME_BASENAME, server.hostname)
|
||||
|
||||
- thread_name = "%s_%s" % (THREAD_SYNC_TIME_BASENAME, server)
|
||||
+ # syncing with the same server running
|
||||
if threadMgr.get(thread_name):
|
||||
- #syncing with the same server running
|
||||
return
|
||||
|
||||
- threadMgr.add(AnacondaThread(name=thread_name, target=one_time_sync,
|
||||
- args=(server, callback)))
|
||||
+ threadMgr.add(AnacondaThread(
|
||||
+ name=thread_name,
|
||||
+ target=_one_time_sync,
|
||||
+ args=(server, callback)
|
||||
+ ))
|
||||
--
|
||||
2.23.0
|
||||
@ -1,406 +0,0 @@
|
||||
From 4bc1b7305199fffc78439ab1ad1cdb8272988d52 Mon Sep 17 00:00:00 2001
|
||||
From: Vendula Poncova <vponcova@redhat.com>
|
||||
Date: Fri, 3 Jul 2020 12:21:11 +0200
|
||||
Subject: [PATCH] Use the structure for time sources in the Timezone module
|
||||
|
||||
Modify the Timezone module to work with the DBus structures for time sources
|
||||
instead of the strings. Rename the DBus property NTPServers to TimeSources.
|
||||
---
|
||||
pyanaconda/modules/timezone/installation.py | 14 ++-
|
||||
pyanaconda/modules/timezone/timezone.py | 44 ++++---
|
||||
.../modules/timezone/timezone_interface.py | 34 +++---
|
||||
.../pyanaconda_tests/module_timezone_test.py | 107 ++++++++++++++----
|
||||
4 files changed, 141 insertions(+), 58 deletions(-)
|
||||
|
||||
diff --git a/pyanaconda/modules/timezone/installation.py b/pyanaconda/modules/timezone/installation.py
|
||||
index 6383df1103..c3ea4d7179 100644
|
||||
--- a/pyanaconda/modules/timezone/installation.py
|
||||
+++ b/pyanaconda/modules/timezone/installation.py
|
||||
@@ -145,12 +145,14 @@ def run(self):
|
||||
return
|
||||
|
||||
chronyd_conf_path = os.path.normpath(self._sysroot + ntp.NTP_CONFIG_FILE)
|
||||
- pools, servers = ntp.internal_to_pools_and_servers(self._ntp_servers)
|
||||
|
||||
if os.path.exists(chronyd_conf_path):
|
||||
log.debug("Modifying installed chrony configuration")
|
||||
try:
|
||||
- ntp.save_servers_to_config(pools, servers, conf_file_path=chronyd_conf_path)
|
||||
+ ntp.save_servers_to_config(
|
||||
+ self._ntp_servers,
|
||||
+ conf_file_path=chronyd_conf_path
|
||||
+ )
|
||||
except ntp.NTPconfigError as ntperr:
|
||||
log.warning("Failed to save NTP configuration: %s", ntperr)
|
||||
|
||||
@@ -160,9 +162,11 @@ def run(self):
|
||||
log.debug("Creating chrony configuration based on the "
|
||||
"configuration from installation environment")
|
||||
try:
|
||||
- ntp.save_servers_to_config(pools, servers,
|
||||
- conf_file_path=ntp.NTP_CONFIG_FILE,
|
||||
- out_file_path=chronyd_conf_path)
|
||||
+ ntp.save_servers_to_config(
|
||||
+ self._ntp_servers,
|
||||
+ conf_file_path=ntp.NTP_CONFIG_FILE,
|
||||
+ out_file_path=chronyd_conf_path
|
||||
+ )
|
||||
except ntp.NTPconfigError as ntperr:
|
||||
log.warning("Failed to save NTP configuration without chrony package: %s",
|
||||
ntperr)
|
||||
diff --git a/pyanaconda/modules/timezone/timezone.py b/pyanaconda/modules/timezone/timezone.py
|
||||
index 0678072978..ff89d1ea77 100644
|
||||
--- a/pyanaconda/modules/timezone/timezone.py
|
||||
+++ b/pyanaconda/modules/timezone/timezone.py
|
||||
@@ -18,10 +18,12 @@
|
||||
# Red Hat, Inc.
|
||||
#
|
||||
from pyanaconda.core.configuration.anaconda import conf
|
||||
+from pyanaconda.core.constants import TIME_SOURCE_SERVER
|
||||
from pyanaconda.core.dbus import DBus
|
||||
from pyanaconda.core.signal import Signal
|
||||
from pyanaconda.modules.common.base import KickstartService
|
||||
from pyanaconda.modules.common.constants.services import TIMEZONE
|
||||
+from pyanaconda.modules.common.structures.timezone import TimeSourceData
|
||||
from pyanaconda.timezone import NTP_PACKAGE
|
||||
from pyanaconda.modules.common.containers import TaskContainer
|
||||
from pyanaconda.modules.common.structures.requirement import Requirement
|
||||
@@ -48,8 +50,8 @@ def __init__(self):
|
||||
self.ntp_enabled_changed = Signal()
|
||||
self._ntp_enabled = True
|
||||
|
||||
- self.ntp_servers_changed = Signal()
|
||||
- self._ntp_servers = []
|
||||
+ self.time_sources_changed = Signal()
|
||||
+ self._time_sources = []
|
||||
|
||||
# FIXME: temporary workaround until PAYLOAD module is available
|
||||
self._ntp_excluded = False
|
||||
@@ -70,7 +72,17 @@ def process_kickstart(self, data):
|
||||
self.set_timezone(data.timezone.timezone)
|
||||
self.set_is_utc(data.timezone.isUtc)
|
||||
self.set_ntp_enabled(not data.timezone.nontp)
|
||||
- self.set_ntp_servers(data.timezone.ntpservers)
|
||||
+
|
||||
+ servers = []
|
||||
+
|
||||
+ for hostname in data.timezone.ntpservers:
|
||||
+ server = TimeSourceData()
|
||||
+ server.type = TIME_SOURCE_SERVER
|
||||
+ server.hostname = hostname
|
||||
+ server.options = ["iburst"]
|
||||
+ servers.append(server)
|
||||
+
|
||||
+ self.set_time_sources(servers)
|
||||
|
||||
def setup_kickstart(self, data):
|
||||
"""Set up the kickstart data."""
|
||||
@@ -78,8 +90,12 @@ def setup_kickstart(self, data):
|
||||
data.timezone.isUtc = self.is_utc
|
||||
data.timezone.nontp = not self.ntp_enabled
|
||||
|
||||
- if self.ntp_enabled:
|
||||
- data.timezone.ntpservers = list(self.ntp_servers)
|
||||
+ if not self.ntp_enabled:
|
||||
+ return
|
||||
+
|
||||
+ data.timezone.ntpservers = [
|
||||
+ server.hostname for server in self.time_sources
|
||||
+ ]
|
||||
|
||||
@property
|
||||
def timezone(self):
|
||||
@@ -115,15 +131,15 @@ def set_ntp_enabled(self, ntp_enabled):
|
||||
log.debug("NTP is set to %s.", ntp_enabled)
|
||||
|
||||
@property
|
||||
- def ntp_servers(self):
|
||||
- """Return a list of NTP servers."""
|
||||
- return self._ntp_servers
|
||||
+ def time_sources(self):
|
||||
+ """Return a list of time sources."""
|
||||
+ return self._time_sources
|
||||
|
||||
- def set_ntp_servers(self, servers):
|
||||
- """Set NTP servers."""
|
||||
- self._ntp_servers = list(servers)
|
||||
- self.ntp_servers_changed.emit()
|
||||
- log.debug("NTP servers are set to %s.", servers)
|
||||
+ def set_time_sources(self, servers):
|
||||
+ """Set time sources."""
|
||||
+ self._time_sources = list(servers)
|
||||
+ self.time_sources_changed.emit()
|
||||
+ log.debug("Time sources are set to: %s", servers)
|
||||
|
||||
def collect_requirements(self):
|
||||
"""Return installation requirements for this module.
|
||||
@@ -168,6 +184,6 @@ def install_with_tasks(self):
|
||||
ConfigureNTPTask(
|
||||
sysroot=conf.target.system_root,
|
||||
ntp_enabled=self.ntp_enabled,
|
||||
- ntp_servers=self.ntp_servers
|
||||
+ ntp_servers=self.time_sources
|
||||
)
|
||||
]
|
||||
diff --git a/pyanaconda/modules/timezone/timezone_interface.py b/pyanaconda/modules/timezone/timezone_interface.py
|
||||
index 03c5003f1e..f36e0b3723 100644
|
||||
--- a/pyanaconda/modules/timezone/timezone_interface.py
|
||||
+++ b/pyanaconda/modules/timezone/timezone_interface.py
|
||||
@@ -17,13 +17,15 @@
|
||||
# License and may only be used or replicated with the express permission of
|
||||
# Red Hat, Inc.
|
||||
#
|
||||
-from pyanaconda.modules.common.constants.services import TIMEZONE
|
||||
-from pyanaconda.modules.common.containers import TaskContainer
|
||||
from dasbus.server.property import emits_properties_changed
|
||||
from dasbus.typing import * # pylint: disable=wildcard-import
|
||||
-from pyanaconda.modules.common.base import KickstartModuleInterface
|
||||
from dasbus.server.interface import dbus_interface
|
||||
|
||||
+from pyanaconda.modules.common.base import KickstartModuleInterface
|
||||
+from pyanaconda.modules.common.constants.services import TIMEZONE
|
||||
+from pyanaconda.modules.common.containers import TaskContainer
|
||||
+from pyanaconda.modules.common.structures.timezone import TimeSourceData
|
||||
+
|
||||
|
||||
@dbus_interface(TIMEZONE.interface_name)
|
||||
class TimezoneInterface(KickstartModuleInterface):
|
||||
@@ -34,7 +36,7 @@ def connect_signals(self):
|
||||
self.watch_property("Timezone", self.implementation.timezone_changed)
|
||||
self.watch_property("IsUTC", self.implementation.is_utc_changed)
|
||||
self.watch_property("NTPEnabled", self.implementation.ntp_enabled_changed)
|
||||
- self.watch_property("NTPServers", self.implementation.ntp_servers_changed)
|
||||
+ self.watch_property("TimeSources", self.implementation.time_sources_changed)
|
||||
|
||||
@property
|
||||
def Timezone(self) -> Str:
|
||||
@@ -91,22 +93,26 @@ def SetNTPEnabled(self, ntp_enabled: Bool):
|
||||
self.implementation.set_ntp_enabled(ntp_enabled)
|
||||
|
||||
@property
|
||||
- def NTPServers(self) -> List[Str]:
|
||||
- """A list of NTP servers.
|
||||
+ def TimeSources(self) -> List[Structure]:
|
||||
+ """A list of time sources.
|
||||
|
||||
- :return: a list of servers
|
||||
+ :return: a list of time source data
|
||||
+ :rtype: a list of structures of the type TimeSourceData
|
||||
"""
|
||||
- return self.implementation.ntp_servers
|
||||
+ return TimeSourceData.to_structure_list(
|
||||
+ self.implementation.time_sources
|
||||
+ )
|
||||
|
||||
@emits_properties_changed
|
||||
- def SetNTPServers(self, servers: List[Str]):
|
||||
- """Set the NTP servers.
|
||||
+ def SetTimeSources(self, sources: List[Structure]):
|
||||
+ """Set the time sources.
|
||||
|
||||
- Example: [ntp.cesnet.cz]
|
||||
-
|
||||
- :param servers: a list of servers
|
||||
+ :param sources: a list of time sources
|
||||
+ :type sources: a list of structures of the type TimeSourceData
|
||||
"""
|
||||
- self.implementation.set_ntp_servers(servers)
|
||||
+ self.implementation.set_time_sources(
|
||||
+ TimeSourceData.from_structure_list(sources)
|
||||
+ )
|
||||
|
||||
def ConfigureNTPServiceEnablementWithTask(self, ntp_excluded: Bool) -> ObjPath:
|
||||
"""Enable or disable NTP service.
|
||||
diff --git a/tests/nosetests/pyanaconda_tests/module_timezone_test.py b/tests/nosetests/pyanaconda_tests/module_timezone_test.py
|
||||
index f991f1e992..bb751d6f4b 100644
|
||||
--- a/tests/nosetests/pyanaconda_tests/module_timezone_test.py
|
||||
+++ b/tests/nosetests/pyanaconda_tests/module_timezone_test.py
|
||||
@@ -23,8 +23,13 @@
|
||||
from shutil import copytree, copyfile
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
+from dasbus.structure import compare_data
|
||||
+from dasbus.typing import * # pylint: disable=wildcard-import
|
||||
+
|
||||
+from pyanaconda.core.constants import TIME_SOURCE_SERVER, TIME_SOURCE_POOL
|
||||
from pyanaconda.modules.common.constants.services import TIMEZONE
|
||||
from pyanaconda.modules.common.errors.installation import TimezoneConfigurationError
|
||||
+from pyanaconda.modules.common.structures.timezone import TimeSourceData
|
||||
from pyanaconda.modules.timezone.installation import ConfigureNTPTask, ConfigureTimezoneTask, \
|
||||
ConfigureNTPServiceEnablementTask
|
||||
from pyanaconda.modules.common.structures.kickstart import KickstartReport
|
||||
@@ -33,7 +38,7 @@
|
||||
from pyanaconda.ntp import NTP_CONFIG_FILE, NTPconfigError
|
||||
from tests.nosetests.pyanaconda_tests import check_kickstart_interface, \
|
||||
patch_dbus_publish_object, PropertiesChangedCallback, check_task_creation, \
|
||||
- patch_dbus_get_proxy, check_task_creation_list
|
||||
+ patch_dbus_get_proxy, check_task_creation_list, check_dbus_property
|
||||
from pyanaconda.timezone import NTP_SERVICE
|
||||
|
||||
|
||||
@@ -50,6 +55,14 @@ def setUp(self):
|
||||
self.callback = PropertiesChangedCallback()
|
||||
self.timezone_interface.PropertiesChanged.connect(self.callback)
|
||||
|
||||
+ def _check_dbus_property(self, *args, **kwargs):
|
||||
+ check_dbus_property(
|
||||
+ self,
|
||||
+ TIMEZONE,
|
||||
+ self.timezone_interface,
|
||||
+ *args, **kwargs
|
||||
+ )
|
||||
+
|
||||
def kickstart_properties_test(self):
|
||||
"""Test kickstart properties."""
|
||||
self.assertEqual(self.timezone_interface.KickstartCommands, ["timezone"])
|
||||
@@ -76,12 +89,24 @@ def ntp_property_test(self):
|
||||
self.assertEqual(self.timezone_interface.NTPEnabled, False)
|
||||
self.callback.assert_called_once_with(TIMEZONE.interface_name, {'NTPEnabled': False}, [])
|
||||
|
||||
- def ntp_servers_property_test(self):
|
||||
- """Test the NTPServers property."""
|
||||
- self.timezone_interface.SetNTPServers(["ntp.cesnet.cz"])
|
||||
- self.assertEqual(self.timezone_interface.NTPServers, ["ntp.cesnet.cz"])
|
||||
- self.callback.assert_called_once_with(
|
||||
- TIMEZONE.interface_name, {'NTPServers': ["ntp.cesnet.cz"]}, [])
|
||||
+ def time_sources_property_test(self):
|
||||
+ """Test the TimeSources property."""
|
||||
+ server = {
|
||||
+ "type": get_variant(Str, TIME_SOURCE_SERVER),
|
||||
+ "hostname": get_variant(Str, "ntp.cesnet.cz"),
|
||||
+ "options": get_variant(List[Str], ["iburst"]),
|
||||
+ }
|
||||
+
|
||||
+ pool = {
|
||||
+ "type": get_variant(Str, TIME_SOURCE_POOL),
|
||||
+ "hostname": get_variant(Str, "0.fedora.pool.ntp.org"),
|
||||
+ "options": get_variant(List[Str], []),
|
||||
+ }
|
||||
+
|
||||
+ self._check_dbus_property(
|
||||
+ "TimeSources",
|
||||
+ [server, pool]
|
||||
+ )
|
||||
|
||||
def _test_kickstart(self, ks_in, ks_out):
|
||||
check_kickstart_interface(self, self.timezone_interface, ks_in, ks_out)
|
||||
@@ -162,10 +187,19 @@ def install_with_tasks_configured_test(self, publisher):
|
||||
self.timezone_interface.SetNTPEnabled(False)
|
||||
# --nontp and --ntpservers are mutually exclusive in kicstart but
|
||||
# there is no such enforcement in the module so for testing this is ok
|
||||
- self.timezone_interface.SetNTPServers([
|
||||
- "clock1.example.com",
|
||||
- "clock2.example.com",
|
||||
- ])
|
||||
+
|
||||
+ server = TimeSourceData()
|
||||
+ server.type = TIME_SOURCE_SERVER
|
||||
+ server.hostname = "clock1.example.com"
|
||||
+ server.options = ["iburst"]
|
||||
+
|
||||
+ pool = TimeSourceData()
|
||||
+ pool.type = TIME_SOURCE_POOL
|
||||
+ pool.hostname = "clock2.example.com"
|
||||
+
|
||||
+ self.timezone_interface.SetTimeSources(
|
||||
+ TimeSourceData.to_structure_list([server, pool])
|
||||
+ )
|
||||
|
||||
task_classes = [
|
||||
ConfigureTimezoneTask,
|
||||
@@ -182,10 +216,9 @@ def install_with_tasks_configured_test(self, publisher):
|
||||
# ConfigureNTPTask
|
||||
obj = task_objs[1]
|
||||
self.assertEqual(obj.implementation._ntp_enabled, False)
|
||||
- self.assertEqual(obj.implementation._ntp_servers, [
|
||||
- "clock1.example.com",
|
||||
- "clock2.example.com",
|
||||
- ])
|
||||
+ self.assertEqual(len(obj.implementation._ntp_servers), 2)
|
||||
+ self.assertTrue(compare_data(obj.implementation._ntp_servers[0], server))
|
||||
+ self.assertTrue(compare_data(obj.implementation._ntp_servers[1], pool))
|
||||
|
||||
@patch_dbus_publish_object
|
||||
def configure_ntp_service_enablement_default_test(self, publisher):
|
||||
@@ -354,13 +387,13 @@ class NTPTasksTestCase(unittest.TestCase):
|
||||
|
||||
def ntp_task_success_test(self):
|
||||
"""Test the success cases for NTP setup D-Bus task."""
|
||||
- self._test_ntp_inputs(False, False, ["unique.ntp.server", "another.unique.server"])
|
||||
- self._test_ntp_inputs(False, True, ["unique.ntp.server", "another.unique.server"])
|
||||
+ self._test_ntp_inputs(False, False)
|
||||
+ self._test_ntp_inputs(False, True)
|
||||
|
||||
def ntp_overwrite_test(self):
|
||||
"""Test overwriting existing config for NTP setup D-Bus task."""
|
||||
- self._test_ntp_inputs(True, True, ["unique.ntp.server", "another.unique.server"])
|
||||
- self._test_ntp_inputs(True, False, ["unique.ntp.server", "another.unique.server"])
|
||||
+ self._test_ntp_inputs(True, True)
|
||||
+ self._test_ntp_inputs(True, False)
|
||||
|
||||
def ntp_save_failure_test(self):
|
||||
"""Test failure when saving NTP config in D-Bus task."""
|
||||
@@ -368,6 +401,25 @@ def ntp_save_failure_test(self):
|
||||
self._test_ntp_exception(True)
|
||||
self._test_ntp_exception(False)
|
||||
|
||||
+ def _get_test_sources(self):
|
||||
+ """Get a list of sources"""
|
||||
+ server = TimeSourceData()
|
||||
+ server.type = TIME_SOURCE_SERVER
|
||||
+ server.hostname = "unique.ntp.server"
|
||||
+ server.options = ["iburst"]
|
||||
+
|
||||
+ pool = TimeSourceData()
|
||||
+ pool.type = TIME_SOURCE_POOL
|
||||
+ pool.hostname = "another.unique.server"
|
||||
+
|
||||
+ return [server, pool]
|
||||
+
|
||||
+ def _get_expected_lines(self):
|
||||
+ return [
|
||||
+ "server unique.ntp.server iburst\n",
|
||||
+ "pool another.unique.server\n"
|
||||
+ ]
|
||||
+
|
||||
@patch("pyanaconda.modules.timezone.installation.ntp.save_servers_to_config",
|
||||
side_effect=NTPconfigError)
|
||||
def _test_ntp_exception(self, make_chronyd, mock_save):
|
||||
@@ -376,11 +428,14 @@ def _test_ntp_exception(self, make_chronyd, mock_save):
|
||||
with self.assertLogs("anaconda.modules.timezone.installation", level="WARNING"):
|
||||
self._execute_task(sysroot, True, ["ntp.example.com"])
|
||||
|
||||
- def _test_ntp_inputs(self, make_chronyd, ntp_enabled, ntp_servers):
|
||||
+ def _test_ntp_inputs(self, make_chronyd, ntp_enabled):
|
||||
+ ntp_servers = self._get_test_sources()
|
||||
+ expected_lines = self._get_expected_lines()
|
||||
+
|
||||
with tempfile.TemporaryDirectory() as sysroot:
|
||||
self._setup_environment(sysroot, make_chronyd)
|
||||
self._execute_task(sysroot, ntp_enabled, ntp_servers)
|
||||
- self._validate_ntp_config(sysroot, make_chronyd, ntp_enabled, ntp_servers)
|
||||
+ self._validate_ntp_config(sysroot, make_chronyd, ntp_enabled, expected_lines)
|
||||
|
||||
def _setup_environment(self, sysroot, make_chronyd):
|
||||
os.mkdir(sysroot + "/etc")
|
||||
@@ -395,12 +450,14 @@ def _execute_task(self, sysroot, ntp_enabled, ntp_servers):
|
||||
)
|
||||
task.run()
|
||||
|
||||
- def _validate_ntp_config(self, sysroot, was_present, was_enabled, expected_servers):
|
||||
+ def _validate_ntp_config(self, sysroot, was_present, was_enabled, expected_lines):
|
||||
if was_enabled:
|
||||
with open(sysroot + NTP_CONFIG_FILE) as fobj:
|
||||
- all_lines = "\n".join(fobj.readlines())
|
||||
- for server in expected_servers:
|
||||
- self.assertIn(server, all_lines)
|
||||
+ all_lines = fobj.readlines()
|
||||
+
|
||||
+ for line in expected_lines:
|
||||
+ self.assertIn(line, all_lines)
|
||||
+
|
||||
elif not was_present:
|
||||
self.assertFalse(os.path.exists(sysroot + NTP_CONFIG_FILE))
|
||||
|
||||
--
|
||||
2.23.0
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user