### Install Documentation Dependencies Source: https://github.com/oamg/convert2rhel/blob/main/docs/source/meta.md Command to install required Sphinx packages on Fedora. ```default $ sudo dnf install python3-sphinx python3-sphinx-autodoc-typehints.noarchpython3-sphinx ``` -------------------------------- ### Install Pre-commit Hooks Source: https://github.com/oamg/convert2rhel/blob/main/CONTRIBUTING.md Installs pre-commit hooks into the repository. This command is also included in the `make install` process. ```bash pre-commit install --install-hooks ``` -------------------------------- ### Install Dependencies and Build Container Images Source: https://github.com/oamg/convert2rhel/blob/main/convert2rhel/unit_tests/README.md Run this command in the project's root directory to install necessary dependencies, pre-commit hooks, and build container images. It creates hidden files to optimize subsequent runs. ```bash # Install dependencies, pre-commit and container images make install ``` -------------------------------- ### Install RHEL GPG Keys Source: https://context7.com/oamg/convert2rhel/llms.txt Installs the necessary GPG keys required for RHEL packages. ```python pkghandler.install_gpg_keys() ``` -------------------------------- ### Initialize Development Environment Source: https://github.com/oamg/convert2rhel/blob/main/CONTRIBUTING.md Creates a Python 3 virtual environment, installs dependencies, and configures pre-commit hooks. ```bash make install ``` -------------------------------- ### Reference Python Objects in ReST Source: https://github.com/oamg/convert2rhel/blob/main/docs/source/meta.md Syntax examples for referencing modules, classes, and attributes in documentation. ```default 1. :mod:`actions`, // works in docstrings, doesn't work in rst 2. :class:`Action`, // works in docstrings, doesn't work in rst 3. :mod:`.actions`, // looks fo all objects which end with the suffix `.actions`. // As it finds two: convert2rhel.actions and convert2rhel.unit_tests.actions // it takes the shortest of them 4. :mod:`convert2rhel.actions`, // fully-qualified name 5. :mod:`~convert2rhel.unit_tests.actions`, // cuts the title to the last part 6. :attr:`.Action.id`, 7. :attr:`.Action.id`\ s, // see the note 8. `.actions`. // text in backticks recognized as inline code by default. ``` -------------------------------- ### Register a Change with BackupController Source: https://github.com/oamg/convert2rhel/wiki/BackupController Example of instantiating a RestorableChange and pushing it to the controller stack. ```python from convert2rhel.backup import backup_control from convert2rhel.backup.files import RestorableFile VERY_IMPORTANT_FILE_TO_BACKUP = "/etc/super-very-most-important-file.txt" restorable_file = RestorableFile(VERY_IMPORTANT_FILE_TO_BACKUP) backup_control.push(restorable_file) ``` -------------------------------- ### Install VS Code Dev Container Extension Source: https://github.com/oamg/convert2rhel/blob/main/CONTRIBUTING.md Use this identifier to install the required Dev Container extension in VS Code. ```text ms-vscode-remote.remote-containers ``` -------------------------------- ### Get Packages for Replacement Source: https://context7.com/oamg/convert2rhel/llms.txt Fetches system packages that are candidates for replacement during the RHEL conversion process. ```python system_pkgs = pkghandler.get_system_packages_for_replacement() ``` -------------------------------- ### Action Class with Dependencies Source: https://github.com/oamg/convert2rhel/wiki/Action-Framework This example shows how to define dependencies for an action class. The dependent action will only execute if all specified dependencies succeed. Dependencies can be referenced by string ID or by the class's ID attribute. ```python __metaclass__ = type from convert2rhel import actions import logging logger = logging.getLogger(__name__) class YourDependencyAction(actions.Action) id = "NICE_DEPENDENCY" def run(self): super(YourDependencyAction, self).run() logger.info("This action class will run first") perform_some_dependency_thing() class YourAction(actions.Action): id = "" dependencies = ( "NICE_DEPENDENCY", # Or, you could use, which ideally is the same as the above. YourDependencyAction.id, ) def run(self): super(YourAction, self).run() logger.info("This action will run if `YourDependencyAction` succeed.") now_we_execute_this_action() ``` -------------------------------- ### Query and Manage RPM Packages Source: https://context7.com/oamg/convert2rhel/llms.txt Retrieve information about installed packages and filter them by GPG key IDs. ```python from convert2rhel import pkghandler # Get information about installed packages all_packages = pkghandler.get_installed_pkg_information() # Returns list of PackageInformation namedtuples # Get specific package information kernel_info = pkghandler.get_installed_pkg_information("kernel") for pkg in kernel_info: print(f"Name: {pkg.nevra.name}") print(f"Version: {pkg.nevra.version}") print(f"Release: {pkg.nevra.release}") print(f"Arch: {pkg.nevra.arch}") print(f"Vendor: {pkg.vendor}") print(f"Key ID: {pkg.key_id}") # Get packages signed by specific GPG key IDs rhel_key_ids = ["199e2f91fd431d51", "5326810137017186"] rhel_signed_pkgs = pkghandler.get_installed_pkgs_by_key_id(rhel_key_ids) ``` -------------------------------- ### Display Action Framework Report Messages Source: https://github.com/oamg/convert2rhel/wiki/Action-Framework Examples of console output generated by the Action Framework when tasks encounter errors or complete successfully. ```bash [03/31/2023 17:43:52] TASK - [Prepare: Conversion analysis report] ********************************** (ERROR) ErrorAction.ERROR: ERROR MESSAGE (OVERRIDABLE) OverridableAction.OVERRIDABLE: OVERRIDABLE MESSAGE (WARNING) WarningAction.WARNING: WARNING MESSAGE ``` ```bash [03/31/2023 17:43:52] TASK - [Prepare: Conversion analysis report] ********************************** No problems detected during the analysis! ``` -------------------------------- ### Check if RPM is Installed Source: https://context7.com/oamg/convert2rhel/llms.txt Checks whether a specific RPM package is currently installed on the system. ```python if system_info.is_rpm_installed("httpd"): print("Apache is installed") ``` -------------------------------- ### Manage System Backups and Rollbacks Source: https://context7.com/oamg/convert2rhel/llms.txt Use the BackupController to track file modifications, package installations, and GPG key imports for safe rollback. Custom changes can be implemented by extending the RestorableChange class. ```python from convert2rhel.backup import backup_control, RestorableChange, BACKUP_DIR from convert2rhel.backup.files import RestorableFile from convert2rhel.backup.packages import RestorablePackageSet from convert2rhel.backup.certs import RestorableRpmKey # Backup a file before modification backup_control.push(RestorableFile("/etc/yum.repos.d/myrepo.repo")) # Now safe to modify the file - will be restored on rollback with open("/etc/yum.repos.d/myrepo.repo", "w") as f: f.write("[myrepo]\nbaseurl=http://example.com/repo\n") # Install packages with automatic backup for rollback pkg_set = RestorablePackageSet( ["subscription-manager", "python3-subscription-manager-rhsm"], custom_releasever="8", set_releasever=True ) backup_control.push(pkg_set) # Import GPG key with rollback support gpg_key = RestorableRpmKey("/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release") backup_control.push(gpg_key) # Implement custom RestorableChange class MyRestorableChange(RestorableChange): def __init__(self, config_path): super(MyRestorableChange, self).__init__() self.config_path = config_path self.original_content = None def enable(self): """Backup current state before making changes.""" super(MyRestorableChange, self).enable() with open(self.config_path, 'r') as f: self.original_content = f.read() def restore(self): """Restore to original state during rollback.""" super(MyRestorableChange, self).restore() if self.original_content is not None: with open(self.config_path, 'w') as f: f.write(self.original_content) # Trigger rollback (typically handled by main.py) try: backup_control.pop_all() except IndexError: print("No backups to restore") # Check if rollback had failures if backup_control.rollback_failed: print("Rollback failures:", backup_control.rollback_failures) ``` -------------------------------- ### Get Third-Party Packages Source: https://context7.com/oamg/convert2rhel/llms.txt Retrieves a list of third-party packages not signed by OS or RHEL keys. Use this to identify external dependencies before conversion. ```python third_party = pkghandler.get_third_party_pkgs() pkghandler.print_pkg_info(third_party) ``` -------------------------------- ### Get Original and RHEL GPG Key IDs Source: https://context7.com/oamg/convert2rhel/llms.txt Retrieves the GPG key IDs for the original operating system and the target RHEL system. ```python orig_key_ids = system_info.key_ids_orig_os rhel_key_ids = system_info.key_ids_rhel ``` -------------------------------- ### Get Enabled RHEL Repositories Source: https://context7.com/oamg/convert2rhel/llms.txt Retrieves a list of enabled RHEL repositories, taking into account the `--no-rhsm` option. ```python enabled_repos = system_info.get_enabled_rhel_repos() ``` -------------------------------- ### Get Excluded and Swap Packages Source: https://context7.com/oamg/convert2rhel/llms.txt Retrieves lists of packages that should be excluded or swapped during the conversion process, including a mapping of old to new packages. ```python excluded = system_info.excluded_pkgs swap_pkgs = system_info.swap_pkgs # Dict: {old_pkg: new_pkg} repofile_pkgs = system_info.repofile_pkgs ``` -------------------------------- ### Get NEVRA and NVRA Strings Source: https://context7.com/oamg/convert2rhel/llms.txt Extracts the NEVRA (Name-Epoch-Version-Release-Architecture) or NVRA (Name-Version-Release-Architecture) string from a package object. ```python nevra = pkghandler.get_pkg_nevra(pkg_obj) # e.g., "kernel-4.18.0-305.el8.x86_64" nvra = pkghandler.get_pkg_nvra(pkg_obj) # Without epoch ``` -------------------------------- ### Unit Test with Mocked External Dependency Source: https://github.com/oamg/convert2rhel/blob/main/convert2rhel/unit_tests/README.md Example of a unit test that mocks an external dependency (`package_handler.get_packages_to_update`) to ensure predictable results. Use mocks for unreliable external calls. ```python import mock import package_handler def test_check_for_yum_updates(monkeypatch): packages_to_update_mock = mock.Mock(return_value=["package-1", "package-2"]) monkeypatch.setattr(package_handler, "get_packages_to_update", value=packages_to_update_mock) assert package_handler.get_packages_to_update() is not None packages_to_update_mock.assert_called_once_with(["package-1", "package-2"]) ``` -------------------------------- ### Unit Test Without External Mocks Source: https://github.com/oamg/convert2rhel/blob/main/convert2rhel/unit_tests/README.md Example of a unit test for a simple file archiving function that does not require mocking external dependencies. It sets up temporary files and directories to test the function's behavior. ```python import os import file_handler def test_archive_old_files(tmpdir): tmpdir = str(tmpdir) some_dir = os.path.join(tmpdir, "some_dir") some_file = os.path.join(tmpdir, "some_file.txt") test_data = "test data\n" open(some_file, "w").write(test_data) assert "some_file.txt" in os.listdir(tmpdir) file_handler.archive_old_files(tmpdir) old_files = os.listdir(some_dir) assert len(old_files) == 1 with open(os.path.join(some_dir, old_files[0])) as old_f: assert old_f.read() == test_data ``` -------------------------------- ### Message ID Naming Convention Source: https://github.com/oamg/convert2rhel/wiki/Action-Framework Message IDs must be unique, in past tense, and ideally start with the action taken. They can be unique within a specific Action. ```python id = "SKIPPED_MODIFIED_RPM_FILES_DIFF" # GOOD id = "SKIP_MODIFIED_RPM_FILES_DIFF" # BAD id = "FOUND_MODIFIED_RPM_FILES" # GOOD id = "MODIFIED_RPM_FILES_FOUND" # DISCOURAGED ``` -------------------------------- ### Get RHEL Repository IDs Source: https://context7.com/oamg/convert2rhel/llms.txt Retrieves the default, EUS, or ELS Red Hat Subscription Management (RHSM) repository IDs applicable to the current system. ```python default_repos = system_info.default_rhsm_repoids # e.g., ["rhel-8-for-x86_64-baseos-rpms", "rhel-8-for-x86_64-appstream-rpms"] eus_repos = system_info.eus_rhsm_repoids els_repos = system_info.els_rhsm_repoids ``` -------------------------------- ### Bypass Yum API SIGINT Bug Source: https://github.com/oamg/convert2rhel/blob/main/CONTRIBUTING.md This Python 2 code demonstrates how to avoid calling the yum API directly to bypass a SIGINT signal handling bug. Instead, it calls external binaries like 'rpm' via subprocesses. This example shows catching exceptions from yum API calls and checkSignals. ```python #!/usr/bin/python2 -tt import time from yum import YumBase from rpmUtils.miscutils import checkSignals yb = YumBase() try: #yb.doConfigSetup(init_plugins=False) yb.runTransaction(False) except (BaseException, SystemExit, Exception) as e: print('We were able to catch an exception from runTransaction!') print(type(e)) print(e) print('Sleeping') time.sleep(3) # Hit Ctrl-C # If KeyboardInterrupt is raised, chances are that this did not cause the # problem try: checkSignals() except (BaseException, SystemExit, Exception) as e: print('We were able to catch an exception from checkSignals!') print(type(e)) print(e) finally: print('In the finally block') # If the previous try: except exits immediately without message, then the # issue occurred. # If it raises a KeyboardInterrupt traceback then we're okay. # If it prints out anything then we're either okay or encountering a different # behaviour. ``` -------------------------------- ### Build Documentation Source: https://github.com/oamg/convert2rhel/blob/main/docs/source/meta.md Command to generate HTML documentation from the docs directory. ```default $ make ``` -------------------------------- ### Integrate Red Hat Subscription Manager Source: https://context7.com/oamg/convert2rhel/llms.txt Handle system registration, subscription attachment, and repository management for RHEL. ```python from convert2rhel import subscription # Check if system is already registered if subscription.is_registered(): print("System is already registered with RHSM") # Register system (uses credentials from tool_opts) subscription.register_system() # Attach subscription automatically subscription.attach_subscription() # Or auto-attach subscription subscription.auto_attach_subscription() # Check if Simple Content Access is enabled if subscription.is_sca_enabled(): print("SCA enabled - no subscription attachment needed") # Check if subscription is attached if subscription.is_subscription_attached(): print("Subscription is attached") # Enable/disable RHSM repositories subscription.disable_repos() # Disables all repos by default subscription.enable_repos(["rhel-8-for-x86_64-baseos-rpms", "rhel-8-for-x86_64-appstream-rpms"]) # Get packages needed for subscription-manager pkgs_to_install = subscription.needed_subscription_manager_pkgs() # Returns: ["subscription-manager", "python3-subscription-manager-rhsm", ...] # Install RHEL subscription-manager packages subscription.install_rhel_subscription_manager(pkgs_to_install) # Verify subscription-manager is installed correctly subscription.verify_rhsm_installed() # Refresh subscription information subscription.refresh_subscription_info() # Update RHSM custom facts (breadcrumbs) subscription.update_rhsm_custom_facts() # Unregister system (used during rollback) subscription.unregister_system() # Check if we should subscribe based on provided credentials if subscription.should_subscribe(): subscription.register_system() subscription.attach_subscription() ``` -------------------------------- ### Access Tool Configuration and Settings Source: https://context7.com/oamg/convert2rhel/llms.txt Methods for accessing global tool options and parsing custom configuration files. ```python from convert2rhel.toolopts import tool_opts from convert2rhel.toolopts.config import FileConfig, CliConfig # Access current tool options (populated by CLI class during startup) print(f"Activity: {tool_opts.activity}") # "conversion" or "analysis" print(f"Username: {tool_opts.username}") print(f"Organization: {tool_opts.org}") print(f"Use RHSM: {not tool_opts.no_rhsm}") print(f"EUS enabled: {tool_opts.eus}") print(f"ELS enabled: {tool_opts.els}") print(f"Debug mode: {tool_opts.debug}") print(f"Auto-accept: {tool_opts.autoaccept}") print(f"Restart after: {tool_opts.restart}") # Enabled/disabled repositories print(f"Enable repos: {tool_opts.enablerepo}") print(f"Disable repos: {tool_opts.disablerepo}") # Parse configuration file manually file_config = FileConfig(custom_config="/path/to/convert2rhel.ini") file_config.run() print(f"Config username: {file_config.username}") print(f"Config activation_key: {file_config.activation_key}") # Inhibitor override options from config print(f"Allow incomplete rollback: {file_config.incomplete_rollback}") print(f"Skip tainted kmod check: {file_config.tainted_kernel_module_check_skip}") print(f"Allow older RHEL version: {file_config.allow_older_version}") print(f"Allow unavailable kmods: {file_config.allow_unavailable_kmods}") print(f"Skip kernel currency check: {file_config.skip_kernel_currency_check}") ``` -------------------------------- ### Initialize System Information Source: https://context7.com/oamg/convert2rhel/llms.txt Resolves and initializes system information, which is typically called during the startup of the conversion process. ```python from convert2rhel.systeminfo import system_info, Version system_info.resolve_system_info() ``` -------------------------------- ### Build RPMs Locally Source: https://github.com/oamg/convert2rhel/blob/main/CONTRIBUTING.md Use this command to build RPM packages locally. Requires podman. ```bash make rpms ``` -------------------------------- ### Execute Conversion Actions Source: https://context7.com/oamg/convert2rhel/llms.txt Run pre-conversion checks and post-conversion tasks. ```python # Run pre-PONR actions (system checks, pre_ponr_changes) pre_results = run_pre_actions() # Returns: {"ACTION_ID": {"messages": [...], "result": {...}}, ...} # Run post-PONR actions (conversion, post_conversion) post_results = run_post_actions() ``` -------------------------------- ### Action Dependencies and Ordering Source: https://github.com/oamg/convert2rhel/wiki/Action-Framework Explains the concept of dependencies in the Action Framework, how they ensure code execution order, and how actions can depend on each other. ```APIDOC ## Dependencies in Action Framework ### Description Dependencies are used to ensure that specific code runs before a main action. They are typically used for setups, cleanups, or any action that prepares a specific behavior before a determined action runs. Dependencies also ensure the correct ordering of action runs, as the Action Framework may run actions in different orders by default. ### How Dependencies Work Actions can depend on each other to ensure they only run after the successful completion of a dependent action. This guarantees a consistent execution order. ``` -------------------------------- ### Project Documentation Layout Source: https://github.com/oamg/convert2rhel/blob/main/docs/source/meta.md The directory structure for ReST documentation files. ```default index.rst -- all.rst // Full API docs tree -- meta.rst // Documentation about documentation -- actions.rst // Dedicated page for a topic, can reference the API docs. ``` -------------------------------- ### Implement Custom Conversion Actions Source: https://context7.com/oamg/convert2rhel/llms.txt Extend the Action framework to define custom system checks and reporting during the conversion process. ```python from convert2rhel.actions import Action, STATUS_CODE class MyCustomCheck(Action): """Custom action that checks a specific system condition.""" id = "MY_CUSTOM_CHECK" dependencies = ("ANOTHER_ACTION_ID",) # Optional dependencies def run(self): """Execute the check and set appropriate result.""" super(MyCustomCheck, self).run() # Example: Check if a required package is installed if not self._is_package_installed("required-package"): self.set_result( level="ERROR", id="MISSING_REQUIRED_PACKAGE", title="Required package not found", description="The required-package is not installed on the system.", diagnosis="Package required-package was not found in the RPM database.", remediations="Install the required package using: yum install required-package" ) return # Add informational message (WARNING or INFO level only) self.add_message( level="INFO", id="PACKAGE_FOUND", title="Required package found", description="The required-package is installed and ready for conversion." ) # Success is the default if no set_result is called with error # self.set_result(level="SUCCESS", id="SUCCESS") # Optional explicit success def _is_package_installed(self, pkg_name): from convert2rhel import pkghandler return bool(pkghandler.get_installed_pkg_information(pkg_name)) # Running actions programmatically from convert2rhel.actions import run_pre_actions, run_post_actions ``` -------------------------------- ### Run Pre-commit Hooks Source: https://github.com/oamg/convert2rhel/blob/main/CONTRIBUTING.md Executes pre-commit hooks. Use `--all-files` to run against the entire repository. To bypass hooks during commit, use `git commit --no-verify`. ```bash pre-commit run ``` ```bash pre-commit run --all-files ``` ```bash git commit --no-verify ``` -------------------------------- ### Define Action folder structure Source: https://github.com/oamg/convert2rhel/wiki/Action-Framework The standard directory layout for organizing action modules and sub-modules. ```bash actions/ ├── __init__.py # The main module where all actions related functions and classes are stored. ├── pre_ponr_changes # Module that keep together all pre point of no return actions. │   ├── handle_packages.py │   ├── __init__.py │   ├── kernel_modules.py │   ├── special_cases.py │   ├── subscription.py │   └── transaction.py ├── report.py # The report module where wwe output a summary to the user regarding the action runs. └── system_checks # Module that keep together all system checks actions. ├── convert2rhel_latest.py ├── custom_repos_are_valid.py ├── dbus.py ├── efi.py ├── __init__.py ├── is_loaded_kernel_latest.py ├── package_updates.py ├── readonly_mounts.py └── tainted_kmods.py 3 directories, 22 files ``` -------------------------------- ### View Backup Directory Structure Source: https://github.com/oamg/convert2rhel/wiki/BackupController Displays the file organization within the backup module. ```bash backup/ ├── certs.py # Module to keep track of backup/restore of certifications related material ├── files.py # Module to keep track of backup/restore of anything that is related to a fiel ├── __init__.py ├── packages.py # Module to keep track of backup/restore of anything that is a package (rpm) operation 1 directory, 4 files ``` -------------------------------- ### Generate and view code coverage reports Source: https://github.com/oamg/convert2rhel/blob/main/convert2rhel/unit_tests/README.md Commands to run tests with coverage tracking, generate an HTML report, and open the report in a web browser. ```bash # Run pytest and gather code coverage pytest --cov # Transform the coverage into HTML coverage html # Open it with your browser (Can be any browser, firefox is just an example) firefox htmlcov/index.html ``` -------------------------------- ### Handle Kernel Replacement Scenarios Source: https://context7.com/oamg/convert2rhel/llms.txt Provides functions to manage scenarios related to kernel replacement during the conversion, including updating the RHEL kernel. ```python pkghandler.handle_no_newer_rhel_kernel_available() pkghandler.update_rhel_kernel() ``` -------------------------------- ### Build Copr Builds Locally Source: https://github.com/oamg/convert2rhel/blob/main/CONTRIBUTING.md Use this command to build Copr packages locally. Requires podman, a Copr account, and build permissions. ```bash make copr-build ``` -------------------------------- ### Implement a RestorableChange Class Source: https://github.com/oamg/convert2rhel/wiki/BackupController Template for creating a new backup class. Ensure super() is called in __init__, enable, and restore methods to maintain internal state tracking. ```python from convert2rhel.backup import RestorableChange class RestorableExample(RestorableChange): def __init__(self, ...): """ docstring explaining what the class do """ super(RestorableExample, self).__init__() def enable(self): """docstring for how the backup work""" # Prevent multiple backup if self.enabled: return # Code related to backup # Set the enabled value super(RestorableExample, self).enable() def restore(self): """docstring for how the restore work""" if not self.enabled: return # Code related to restore super(RestorableExample, self).restore() ``` -------------------------------- ### Run Full Test Suite in Containers Source: https://github.com/oamg/convert2rhel/blob/main/convert2rhel/unit_tests/README.md Execute the complete test suite for both CentOS Linux 7 and 8 using this make command. This ensures tests run in isolated environments. ```bash # Running tests in both CentOS Linux 7 and 8 make tests ``` -------------------------------- ### Execute Convert2RHEL CLI Commands Source: https://context7.com/oamg/convert2rhel/llms.txt Various command-line operations for system analysis and conversion, including authentication and repository management. ```bash # Basic conversion with username/password authentication convert2rhel convert -u myusername -p mypassword # Run pre-conversion analysis only (with automatic rollback) convert2rhel analyze -u myusername -p mypassword # Conversion using activation key (recommended for security) convert2rhel convert -k my_activation_key -o my_org_id # Using configuration file for credentials (most secure method) convert2rhel convert -c /path/to/convert2rhel.ini # Conversion without RHSM using custom repositories convert2rhel convert --no-rhsm --enablerepo my-rhel-repo # Enable EUS repositories for RHEL 8.8+ systems convert2rhel convert -k my_activation_key -o my_org_id --eus # Enable ELS repositories for RHEL 7 systems convert2rhel convert -k my_activation_key -o my_org_id --els # Auto-accept all prompts and restart after conversion convert2rhel convert -k my_activation_key -o my_org_id -y --restart # Enable debug output for troubleshooting convert2rhel convert -k my_activation_key -o my_org_id --debug # Specify custom subscription pool convert2rhel convert -u myusername -p mypassword --pool 8a85f98c60c2c2b40160c32447481234 # Auto-attach subscription convert2rhel convert -u myusername -p mypassword --auto-attach ``` -------------------------------- ### Run Integration Test with tmt Source: https://github.com/oamg/convert2rhel/blob/main/tests/integration/README.md This command provisions a CentOS 7 virtual machine locally using the 'virtual' provider and a specified cloud image. It also sets environment variables to enable rebuilding RPM packages for use in the test. Use this to run a specific test plan. ```bash tmt \ --context distro=centos-7 \ run \ -vvv --all \ -e ANSIBLE_BUILD_RPM=build \ -e ANSIBLE_RPM_PROVIDER=local \ provision \ --how virtual \ --image https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2 \ plan \ --name $TEST_PLAN_NAME ``` -------------------------------- ### Access System Properties Source: https://context7.com/oamg/convert2rhel/llms.txt Retrieves various properties of the operating system, such as name, ID, version, architecture, release version, and booted kernel. ```python print(f"OS Name: {system_info.name}") # e.g., "CentOS Linux" print(f"OS ID: {system_info.id}") # e.g., "centos" print(f"Version: {system_info.version}") # Version(major=8, minor=5) print(f"Architecture: {system_info.arch}") # e.g., "x86_64" print(f"Release Version: {system_info.releasever}") # e.g., "8.5" print(f"Booted Kernel: {system_info.booted_kernel}") # e.g., "4.18.0-305.el8.x86_64" ``` -------------------------------- ### Parse Package String Source: https://context7.com/oamg/convert2rhel/llms.txt Parses a package string into its components: name, epoch, version, release, and architecture. ```python name, epoch, version, release, arch = pkghandler.parse_pkg_string( "kernel-0:4.18.0-305.el8.x86_64" ) ``` -------------------------------- ### Open Repository in Dev Container Source: https://github.com/oamg/convert2rhel/blob/main/CONTRIBUTING.md Command to trigger the containerized development environment within VS Code. ```text Dev Containers: Open Folder in Container ``` -------------------------------- ### Basic Action Class Implementation Source: https://github.com/oamg/convert2rhel/wiki/Action-Framework Implement a standard action class for regular checks. Ensure the `id` is always provided. Dependencies are optional and can be omitted if not needed. ```python __metaclass__ = type from convert2rhel import actions import logging logger = logging.getLogger(__name__) class YourAction(actions.Action): # `id` is always required for the Action. id = "YOUR_ACTION" # `dependencies` is optional. If you aciton doesn't have any dependency, # you don't need that field to be present. dependencies = () def run(self): super(YourAction, self).run() logger.task("Performing very important task!") perform_your_very_important_task() ``` -------------------------------- ### Check System Version Components Source: https://context7.com/oamg/convert2rhel/llms.txt Checks specific components of the system's version, such as the major version number, to determine conversion compatibility. ```python if system_info.version.major == 8: print("Converting RHEL 8 derivative") ``` -------------------------------- ### Configure Convert2RHEL via INI File Source: https://context7.com/oamg/convert2rhel/llms.txt Template for storing RHSM credentials and overriding conversion inhibitors. Ensure file permissions are set to 0600. ```ini # /etc/convert2rhel.ini or ~/.convert2rhel.ini # File permissions must be 0600 (owner read/write only) [subscription_manager] # Use either username/password OR activation_key/org (not both) username = my_rhsm_username password = my_rhsm_password # activation_key = my_activation_key # org = my_org_id [host_metering] # Configure host metering: "auto" or "force" # configure_host_metering = auto [inhibitor_overrides] # Override specific conversion inhibitors (use with caution) incomplete_rollback = false tainted_kernel_module_check_skip = false allow_older_version = false allow_unavailable_kmods = false skip_kernel_currency_check = false ``` -------------------------------- ### Convert2RHEL Actions Folder Structure Source: https://github.com/oamg/convert2rhel/wiki/Action-Framework Provides an overview of the directory structure for the Convert2RHEL actions, detailing the purpose of key modules and files. ```APIDOC ## Actions Folder Structure ### Directory Layout ```bash actions/ ├── __init__.py # Main module for action-related functions and classes. ├── pre_ponr_changes # Module for pre point of no return actions. │   ├── handle_packages.py │   ├── __init__.py │   ├── kernel_modules.py │   ├── special_cases.py │   ├── subscription.py │   └── transaction.py ├── report.py # Module for outputting action run summaries. └── system_checks # Module for system check actions. ├── convert2rhel_latest.py ├── custom_repos_are_valid.py ├── dbus.py ├── efi.py ├── __init__.py ├── is_loaded_kernel_latest.py ├── package_updates.py ├── readonly_mounts.py ├── rhel_compatible_kernel.py └── tainted_kmods.py ``` ``` -------------------------------- ### Parse System Release Content Source: https://context7.com/oamg/convert2rhel/llms.txt Manually parses the content of the system release file to extract OS details like name, ID, and version. ```python release_data = system_info.parse_system_release_content("CentOS Linux release 8.5.2111 (Core)") # Returns: {"name": "CentOS Linux", "id": "centos", "version": Version(8, 5), ...} ``` -------------------------------- ### Compare Package Versions Source: https://context7.com/oamg/convert2rhel/llms.txt Compares two package versions. Returns -1 if the first is older, 0 if equal, and 1 if the first is newer. ```python result = pkghandler.compare_package_versions( "kernel-4.18.0-240.el8", "kernel-4.18.0-305.el8" ) ``` -------------------------------- ### Convert2RHEL Module Overview Source: https://github.com/oamg/convert2rhel/blob/main/docs/source/_templates/custom-module-template.rst This section outlines the main components of the Convert2RHEL module, including its attributes, functions, classes, and exceptions. ```APIDOC ## Convert2RHEL Module Documentation ### Description Provides an overview of the Convert2RHEL module, detailing its attributes, functions, classes, exceptions, and submodules. ### Module Attributes .. autosummary:: :toctree: [List of module attributes] ### Functions .. autosummary:: :toctree: :nosignatures: [List of functions] ### Classes .. autosummary:: :toctree: :template: custom-class-template.rst :nosignatures: [List of classes] ### Exceptions .. autosummary:: :toctree: [List of exceptions] ### Submodules .. autosummary:: :toctree: :template: custom-module-template.rst :recursive: [List of submodules] ``` -------------------------------- ### Trigger bulk rollback with pop_all Source: https://github.com/oamg/convert2rhel/wiki/BackupController Iteratively calls pop for all elements in the list to trigger the restore method for each instance. ```python from convert2rhel.backup import backup_control print(len(backup_control._restorables)) # 10 backup_control.pop_all() # Pop all elements and trigger the `restore` method for each instance print(len(backup_control._restorables)) # 0 ``` -------------------------------- ### Generate JSON Conversion Report Source: https://context7.com/oamg/convert2rhel/llms.txt Generates a pre-conversion report in JSON format, summarizing the analysis results. Ensure the output directory exists. ```python from convert2rhel.actions.report import ( summary_as_json, summary_as_txt, pre_conversion_report, post_conversion_report, find_highest_report_level, CONVERT2RHEL_PRE_CONVERSION_JSON_RESULTS, CONVERT2RHEL_POST_CONVERSION_JSON_RESULTS ) # Example action results structure results = { "SUBSCRIBE_SYSTEM": { "messages": [ { "level": 25, # INFO "id": "SUBSCRIPTION_INFO", "title": "Subscription details", "description": "System registered successfully", "diagnosis": "", "remediations": "", "variables": {} } ], "result": { "level": 0, # SUCCESS "id": "SUCCESS", "title": "", "description": "", "diagnosis": "", "remediations": "", "variables": {} } }, "CHECK_KERNEL": { "messages": [], "result": { "level": 152, # OVERRIDABLE "id": "INVALID_KERNEL_VERSION", "title": "Kernel version check failed", "description": "The running kernel is not the latest available.", "diagnosis": "Running kernel 4.18.0-240 is older than available 4.18.0-305.", "remediations": "Update the kernel and reboot: yum update kernel && reboot", "variables": {"running": "4.18.0-240", "available": "4.18.0-305"} } } } # Generate JSON report summary_as_json(results, "/var/log/convert2rhel/convert2rhel-pre-conversion.json") ``` -------------------------------- ### Action Class with Result Setting Source: https://github.com/oamg/convert2rhel/wiki/Action-Framework This action class demonstrates how to set different results (ERROR or WARNING) using `self.set_result()` based on task outcomes. This is typically done when a task fails or has specific conditions. ```python __metaclass__ = type from convert2rhel import actions import logging logger = logging.getLogger(__name__) class YourAction(actions.Action): id = "YOUR_ACTION" def run(self): super(YourAction, self).run() logger.task("Performing a task that will fail :(") has_failed = a_task_that_will_fail() if has_failed: # In case of failure, you need to set the result self.set_result(status="ERROR", error_id="SOME_ERROR", message="It failed :(") else: self.set_result(status="WARNING", error_id="SOME_WARNING", message="It succeed, but with some warnings.") ``` -------------------------------- ### Check if DBus is Running Source: https://context7.com/oamg/convert2rhel/llms.txt Verifies if the DBus service is running, which is a prerequisite for the subscription-manager. ```python if system_info.dbus_running: print("DBus service is running") ``` -------------------------------- ### Returning Messages for Reports Source: https://github.com/oamg/convert2rhel/wiki/Action-Framework Details how to set results and add messages within an Action using `Action.set_result()` and `Action.add_message()`. ```APIDOC ## Returning Messages for the Report ### Action.set_result() #### Description When returning from an `Action`, a result must be set. By default, `Action`s have a `SUCCESS` result. If errors occur, `Action.set_result()` should be called to return an error. The valid `level`s for a result are `ERROR`, `OVERRIDABLE`, `SKIP`, and `SUCCESS`. It is recommended to `return` after calling `Action.set_result()`. ### Action.add_message() #### Description This method is used when an `Action` discovers information that doesn't prevent the conversion but would be useful for the user to know. The valid levels for messages are `WARNING` and `INFO`. ``` -------------------------------- ### Action ID Naming Convention Source: https://github.com/oamg/convert2rhel/wiki/Action-Framework Action IDs should be in CONSTANT_CASE and describe the action being taken using the current tense. Avoid past tense or reversed word order. ```python id = "LIST_THIRD_PARTY_PACKAGES" # GOOD id = "LISTED_THIRD_PARTY_PACKAGES" # BAD id = "BACKUP_REDHAT_RELEASE" # GOOD id = "REDHAT_RELEASE_BACKUP" # DISCOURAGED ``` -------------------------------- ### Generate and Print Conversion Reports Source: https://context7.com/oamg/convert2rhel/llms.txt Functions for generating text-based reports and printing pre/post-conversion status to the console. ```python summary_as_txt(results, "/var/log/convert2rhel/convert2rhel-pre-conversion.txt") # Print pre-conversion report to console pre_conversion_report(results, include_all_reports=True, disable_colors=False) # Print post-conversion report to console post_conversion_report(results, include_all_reports=False, disable_colors=True) # Find highest severity level in results highest_level = find_highest_report_level(results) ``` -------------------------------- ### Run Pytest and Gather Code Coverage Locally Source: https://github.com/oamg/convert2rhel/blob/main/convert2rhel/unit_tests/README.md Execute pytest locally while also gathering code coverage information. This helps identify which parts of the codebase are being tested. ```bash # Run pytest and gather code coverage pytest --cov ``` -------------------------------- ### Update Pre-commit Hooks Source: https://github.com/oamg/convert2rhel/blob/main/CONTRIBUTING.md Automatically bumps the versions of pre-commit hooks to the latest available versions. ```bash pre-commit autoupdate ``` -------------------------------- ### Run Test Suite in Specific CentOS Version Container Source: https://github.com/oamg/convert2rhel/blob/main/convert2rhel/unit_tests/README.md Run the test suite exclusively in either a CentOS Linux 7 or CentOS Linux 8 container. This is useful for targeted testing or debugging specific environment issues. ```bash # Running the tests only in CentOS Linux 7 make tests7 ``` ```bash # Running the tests only in CentOS Linux 8 make tests8 ``` -------------------------------- ### Run Code Linters Source: https://github.com/oamg/convert2rhel/blob/main/CONTRIBUTING.md Executes linting checks to ensure code standardization across the project. ```bash make lint # Runs inside a centos8 container ``` ```bash make lint-locally ``` -------------------------------- ### Check EUS/ELS Eligibility Source: https://context7.com/oamg/convert2rhel/llms.txt Determines if the system is eligible for Extended Update Support (EUS) or Extended Lifecycle Support (ELS) repositories. ```python if system_info.eus_system: print("System eligible for EUS repositories") if system_info.els_system: print("System eligible for ELS repositories") ``` -------------------------------- ### Check for Package Updates Source: https://context7.com/oamg/convert2rhel/llms.txt Determines the total number of packages that have available updates. ```python packages_to_update = pkghandler.get_total_packages_to_update() ``` -------------------------------- ### Run specific tests with pytest Source: https://github.com/oamg/convert2rhel/blob/main/convert2rhel/unit_tests/README.md Executes tests matching the provided substring pattern. ```bash pytest -k test_my_thing ``` -------------------------------- ### Handle Conversion Exit Codes Source: https://context7.com/oamg/convert2rhel/llms.txt Implementation of exit code logic for wrapper scripts to handle conversion results. ```python from convert2rhel.main import ConversionExitCodes ``` ```bash #!/bin/bash convert2rhel analyze -k $ACTIVATION_KEY -o $ORG_ID -y exit_code=$? case $exit_code in 0) echo "Analysis successful - system ready for conversion" ;; 1) echo "Analysis failed due to internal error" ;; 2) echo "Analysis found issues that must be resolved" echo "Check /var/log/convert2rhel/convert2rhel-pre-conversion.json" ;; esac ``` -------------------------------- ### Clear Version Locks Source: https://context7.com/oamg/convert2rhel/llms.txt Removes any version locks that might prevent package upgrades during the conversion process. ```python pkghandler.clear_versionlock() ``` -------------------------------- ### Run Tests Locally with Pytest Source: https://github.com/oamg/convert2rhel/blob/main/convert2rhel/unit_tests/README.md Execute the test suite directly on your local machine using pytest. This method allows for easier debugging with a debugger. ```bash # Make command to run the tests with pytest make tests-locally ``` -------------------------------- ### Trigger individual rollback with pop Source: https://github.com/oamg/convert2rhel/wiki/BackupController Removes the last element from the restorable list and executes its restore method. ```python from convert2rhel.backup import backup_control print(len(backup_control._restorables)) # 10 backup_control.pop() # Pop the last element and trigger the `restore` method for that instance print(len(backup_control._restorables)) # 9 ``` -------------------------------- ### Pass Pytest Arguments to Containerized Tests Source: https://github.com/oamg/convert2rhel/blob/main/convert2rhel/unit_tests/README.md Pass custom arguments to the pytest execution within the container by setting the `PYTEST_ARGS` environment variable. This allows for selective test runs or specific pytest options. ```bash # Run only the test_something test case make tests7 PYTEST_ARGS="-k test_something" ``` ```bash # Print pytest version make tests7 PYTEST_ARGS="--version" ``` ```bash # Print pytest version in both containers make tests PYTEST_ARGS="--version" ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.