From 22574153c62b4bf04bc60e78b16f19ffeb457024 Mon Sep 17 00:00:00 2001 From: xia_qirong Date: Mon, 21 Sep 2020 17:37:08 +0800 Subject: [PATCH 1/2] do not need to verify treeinfo when using nfs --- anaconda.spec | 10 + ...or-verify-valid-installtree-function.patch | 58 +++++ ...repo-is-valid-based-on-treeinfo-file.patch | 54 +++++ ...d-installtree-to-source-module-utils.patch | 107 ++++++++ ...or-a-simple-check-for-DNF-repository.patch | 228 ++++++++++++++++++ 5 files changed, 457 insertions(+) create mode 100644 bugfix-add-tests-for-verify-valid-installtree-function.patch create mode 100644 bugfix-do-not-test-if-repo-is-valid-based-on-treeinfo-file.patch create mode 100644 bugfix-move-verify-valid-installtree-to-source-module-utils.patch create mode 100644 bugfix-rename-function-for-a-simple-check-for-DNF-repository.patch diff --git a/anaconda.spec b/anaconda.spec index f2ac928..e77e78c 100644 --- a/anaconda.spec +++ b/anaconda.spec @@ -31,6 +31,10 @@ Patch9017: bugfix-add-kdump-parameter-into-kernel-cmdline.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 %define dbusver 1.2.3 %define dnfver 3.6.0 @@ -242,6 +246,12 @@ update-desktop-database &> /dev/null || : %{_datadir}/gtk-doc %changelog +* Mon Sep 21 2020 zhangrui - 33.19-2 +- Type:bugfix +- Id:NA +- SUG:NA +- DESC:do not need to verify treeinfo when using nfs + * Thu Aug 27 2020 hanzhijun - 33.19-1 - update version to 33.19 diff --git a/bugfix-add-tests-for-verify-valid-installtree-function.patch b/bugfix-add-tests-for-verify-valid-installtree-function.patch new file mode 100644 index 0000000..cae9609 --- /dev/null +++ b/bugfix-add-tests-for-verify-valid-installtree-function.patch @@ -0,0 +1,58 @@ +From 5dc9b2ee4dde7b6deb477b581759c5f76dcb87b5 Mon Sep 17 00:00:00 2001 +From: Jiri Konecny +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)) diff --git a/bugfix-do-not-test-if-repo-is-valid-based-on-treeinfo-file.patch b/bugfix-do-not-test-if-repo-is-valid-based-on-treeinfo-file.patch new file mode 100644 index 0000000..2da320b --- /dev/null +++ b/bugfix-do-not-test-if-repo-is-valid-based-on-treeinfo-file.patch @@ -0,0 +1,54 @@ +From 6cee8e5a59a9c424d2bc79b5474a749c4f786b40 Mon Sep 17 00:00:00 2001 +From: Jiri Konecny +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 +--- + 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 diff --git a/bugfix-move-verify-valid-installtree-to-source-module-utils.patch b/bugfix-move-verify-valid-installtree-to-source-module-utils.patch new file mode 100644 index 0000000..204a867 --- /dev/null +++ b/bugfix-move-verify-valid-installtree-to-source-module-utils.patch @@ -0,0 +1,107 @@ +From fea8f2db7594482457f1a7f7aebb7ccac4505fa5 Mon Sep 17 00:00:00 2001 +From: Jiri Konecny +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): diff --git a/bugfix-rename-function-for-a-simple-check-for-DNF-repository.patch b/bugfix-rename-function-for-a-simple-check-for-DNF-repository.patch new file mode 100644 index 0000000..1b13069 --- /dev/null +++ b/bugfix-rename-function-for-a-simple-check-for-DNF-repository.patch @@ -0,0 +1,228 @@ +From 92d8d9d3e39eae8e268e3aeff096105b441bbeae Mon Sep 17 00:00:00 2001 +From: Jiri Konecny +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 -- Gitee From 05551e86e9315c1484d88ba8b8819bc0e8a54cf0 Mon Sep 17 00:00:00 2001 From: xia_qirong Date: Mon, 21 Sep 2020 17:40:25 +0800 Subject: [PATCH 2/2] do not need to verify treeinfo when using nfs --- anaconda.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/anaconda.spec b/anaconda.spec index e77e78c..e5a8caf 100644 --- a/anaconda.spec +++ b/anaconda.spec @@ -1,7 +1,7 @@ %define _empty_manifest_terminate_build 0 Name: anaconda Version: 33.19 -Release: 1 +Release: 2 Summary: Graphical system installer License: GPLv2+ and MIT URL: http://fedoraproject.org/wiki/Anaconda -- Gitee