# # The support for package and group requirements # # Copyright (C) 2020 Red Hat, Inc. # # This copyrighted material is made available to anyone wishing to use, # modify, copy, or redistribute it subject to the terms and conditions of # the GNU General Public License v.2, or (at your option) any later version. # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY expressed or implied, including the implied warranties 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, write to the # Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. Any Red Hat trademarks that are incorporated in the # source code or documentation are not subject to the GNU General Public # License and may only be used or replicated with the express permission of # Red Hat, Inc. # import os from pyanaconda.anaconda_loggers import get_module_logger from pyanaconda.core.configuration.anaconda import conf from pyanaconda.core.constants import REQUIREMENT_TYPE_PACKAGE, REQUIREMENT_TYPE_GROUP from pyanaconda.core.hw import detect_virtualized_platform from pyanaconda.localization import find_best_locale_match, is_valid_langcode from pyanaconda.modules.common.constants.services import LOCALIZATION, BOSS from pyanaconda.modules.common.structures.requirement import Requirement from pyanaconda.modules.common.util import is_module_available log = get_module_logger(__name__) def collect_remote_requirements(): """Collect requirements of the DBus modules. :return: a list of requirements """ boss = BOSS.get_proxy() return Requirement.from_structure_list( boss.CollectRequirements() ) def collect_language_requirements(dnf_manager): """Collect requirements for supported languages. :param dnf_manager: a DNF manager :return: a list of requirements """ requirements = [] if not is_module_available(LOCALIZATION): return requirements localization_proxy = LOCALIZATION.get_proxy() locales = [localization_proxy.Language] + localization_proxy.LanguageSupport # Find all available langpacks. packages = dnf_manager.match_available_packages("langpacks-*") # Get all valid langcodes. codes = [p.split('-', 1)[1] for p in packages] codes = list(filter(is_valid_langcode, codes)) # Find the best langpacks to install. for locale in locales: best_locale = find_best_locale_match(locale, codes) if not best_locale: log.warning("Selected locale '%s' does not match " "any available langpacks.", locale) continue requirements.append(Requirement.for_package( package_name="langpacks-" + best_locale, reason="Required to support the locale '{}'.".format(locale) )) return requirements def collect_platform_requirements(dnf_manager): """Collect the requirements for the current platform. :param dnf_manager: a DNF manager :return: a list of requirements """ # Detect the current platform. platform = detect_virtualized_platform() if not platform: return [] # Add a platform specific group. group = "platform-" + platform.lower() if group not in dnf_manager.groups: log.warning("Platform group %s not available.", group) return [] return [Requirement.for_group( group_name=group, reason="Required for the {} platform.".format(platform) )] def collect_driver_disk_requirements(path="/run/install/dd_packages"): """Collect the requirements from the driver updates disk. :param path: a path to the file with a package list :return: a list of requirements """ requirements = [] if not os.path.exists(path): return [] with open(path, "r") as f: for line in f: package = line.strip() requirements.append(Requirement.for_package( package_name=package, reason="Required by the driver updates disk." )) return requirements def apply_requirements(requirements, include_list, exclude_list): """Apply the provided requirements. :param requirements: a list of requirements :param include_list: a list of specs to include in the transaction :param exclude_list: a list of specs to exclude from the transaction """ log.debug("Applying requirements: %s", requirements) for r in requirements: # Generate a spec for the requirement. if r.type == REQUIREMENT_TYPE_PACKAGE: spec = r.name elif r.type == REQUIREMENT_TYPE_GROUP: spec = "@{}".format(r.name) else: log.warning("Unsupported type '%s' of the requirement.", r.type) continue # Check if the requirement can be applied. if spec in conf.payload.ignored_packages: log.debug("Requirement '%s' is ignored by the configuration.", spec) continue if spec in exclude_list: log.debug("Requirement '%s' is ignored because it's excluded.", spec) continue # Apply the requirement. include_list.append(spec) log.debug("Requirement '%s' is applied. Reason: %s", spec, r.reason)