From 2f40d60ec2339bcc965bb36ee0daeb8c246a1716 Mon Sep 17 00:00:00 2001 From: Peter Ajamian Date: Sun, 8 Aug 2021 21:57:45 +1200 Subject: [PATCH 1/8] Do not attempt to update EFI boot in containers. Containers (at least many fo them) will bind-mount /sys which works for most cases but it means that /sys will indicate EFI boot when it is, in fact, the host system that has EFI boot. To fix this we use systemd-detect-virt to see if we're running in a container and if so we don't attempt to update EFI boot. --- migrate2rocky/migrate2rocky.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/migrate2rocky/migrate2rocky.sh b/migrate2rocky/migrate2rocky.sh index 2c9773d..ceadbca 100644 --- a/migrate2rocky/migrate2rocky.sh +++ b/migrate2rocky/migrate2rocky.sh @@ -209,9 +209,8 @@ bin_check() { local -a missing bins bins=( - rpm dnf awk column tee tput mkdir - cat arch sort uniq rmdir rm head - curl sha512sum mktemp + rpm dnf awk column tee tput mkdir cat arch sort uniq + rmdir rm head curl sha512sum mktemp systemd-detect-virt ) if [[ $update_efi ]]; then bins+=(findmnt grub2-mkconfig efibootmgr grep mokutil lsblk) @@ -852,7 +851,8 @@ efi_check () { fi # Now that we know /sys is reliable, use it to check if we are running on EFI or not - if [[ -d /sys/firmware/efi/ ]]; then + if [[ -d /sys/firmware/efi/ ]] && ! systemd-detect-virt --quiet --container + then declare -g update_efi update_efi=true fi From d7f52751d0b0e3e78bace3b659d123b449b2ea76 Mon Sep 17 00:00:00 2001 From: Peter Ajamian Date: Mon, 9 Aug 2021 23:35:39 +1200 Subject: [PATCH 2/8] Prevent attempted writes to /sys and /proc in containers. Containers generally bind-mount /sys and /proc, so if dnf or rpm attempts to write to write to one of them it can cause issues with the host system, or just fail alltogether. We set an rpm macro to prevent this from happening. --- migrate2rocky/migrate2rocky.sh | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/migrate2rocky/migrate2rocky.sh b/migrate2rocky/migrate2rocky.sh index ceadbca..5b523d5 100644 --- a/migrate2rocky/migrate2rocky.sh +++ b/migrate2rocky/migrate2rocky.sh @@ -186,6 +186,9 @@ exit_clean () { if [[ -d "$tmp_dir" ]]; then rm -rf "$tmp_dir" fi + if [[ -f "$container_macros" ]]; then + rm -f "$container_macros" + fi } pre_check () { @@ -609,7 +612,8 @@ $'because continuing with the migration could cause further damage to system.' } convert_info_dir=/root/convert -unset convert_to_rocky reinstall_all_rpms verify_all_rpms update_efi +unset convert_to_rocky reinstall_all_rpms verify_all_rpms update_efi \ + container_macros usage() { printf '%s\n' \ @@ -850,9 +854,13 @@ efi_check () { exit_message "/sys is not accessible." fi - # Now that we know /sys is reliable, use it to check if we are running on EFI or not - if [[ -d /sys/firmware/efi/ ]] && ! systemd-detect-virt --quiet --container - then + # Now that we know /sys is reliable, use it to check if we are running on + # EFI or not + if systemd-detect-virt --quiet --container; then + declare -g container_macros + container_macros=$(mktemp /etc/rpm/macros.zXXXXXX) + printf '%s\n' '%_netsharedpath /sys:/proc' > "$container_macros" + elif [[ -d /sys/firmware/efi/ ]]; then declare -g update_efi update_efi=true fi From 7eb310f907a44c910dbfa127e5c14ec76e62a535 Mon Sep 17 00:00:00 2001 From: Peter Ajamian Date: Sat, 14 Aug 2021 01:35:50 +1200 Subject: [PATCH 3/8] Keep new packages when migrating from Stream until RockyLinux catches up (#96) * CentOS Stream changes * Retain CentOS Stream repositories and packages to avoid version downgrade issues. * Only remove centos-stream-repos from the rpm db, do not actually uninstall the files. * Rename system repositories from CentOS Stream with a "stream-" prefix to avoid clashing with Rockylinux system repository names. * Disable CentOS Stream repositories after the distro-sync. Note that these changes will leave CentOS Stream packages on the system, likely until the next RockyLinux point release. This is intentional to avoid issues with downgrading package versions. * Apply stream logic to epel-next-release. epel-next-release is installed for CentOS stream machines with EPEL. Apply similar logic for epel-next as for CentOS stream. --- migrate2rocky/migrate2rocky.sh | 104 ++++++++++++++++++++++++++++++--- 1 file changed, 97 insertions(+), 7 deletions(-) diff --git a/migrate2rocky/migrate2rocky.sh b/migrate2rocky/migrate2rocky.sh index 5b523d5..744ab7c 100644 --- a/migrate2rocky/migrate2rocky.sh +++ b/migrate2rocky/migrate2rocky.sh @@ -125,6 +125,15 @@ repo_urls=( [rockyappstream]="https://dl.rockylinux.org/pub/rocky/${SUPPORTED_MAJOR}/AppStream/$ARCH/os/" ) +# The repos package for CentOS stream requires special handling. +declare -g -A stream_repos_pkgs +stream_repos_pkgs=( + [rocky-repos]=centos-stream-repos + [epel-release]=epel-next-release +) +# Prefix to add to CentOS stream repo names when renaming them. +stream_prefix=stream- + unset CDPATH exit_message() { @@ -212,8 +221,8 @@ bin_check() { local -a missing bins bins=( - rpm dnf awk column tee tput mkdir cat arch sort uniq - rmdir rm head curl sha512sum mktemp systemd-detect-virt + rpm dnf awk column tee tput mkdir cat arch sort uniq rmdir + rm head curl sha512sum mktemp systemd-detect-virt sed ) if [[ $update_efi ]]; then bins+=(findmnt grub2-mkconfig efibootmgr grep mokutil lsblk) @@ -539,6 +548,22 @@ $'because continuing with the migration could cause further damage to system.' fi done; + # Special Handling for CentOS Stream Repos + installed_sys_stream_repos_pkgs=() + installed_stream_repos_pkgs=() + for p in "${!stream_repos_pkgs[@]}"; do + if [[ ${installed_pkg_map[$p]} && + ${installed_pkg_map[$p]} == "${stream_repos_pkgs[$p]}" ]] + then + # System package that needs to be swapped / disabled + installed_pkg_map[$p]= + installed_sys_stream_repos_pkgs+=( ${stream_repos_pkgs[$p]} ) + elif rpm --quiet -q "${stream_repos_pkgs[$p]}"; then + # Non-system package, repos just need to be disabled. + installed_stream_repos_pkgs+=( ${stream_repos_pkgs[$p]} ) + fi + done + printf '%s\n' '' "We will replace the following $PRETTY_NAME packages with their Rocky Linux 8 equivalents" column -t -s $'\t' -N "Packages to be Removed,Packages to be Installed" < <( for p in "${!installed_pkg_map[@]}"; do @@ -546,8 +571,24 @@ $'because continuing with the migration could cause further damage to system.' done ) + if (( ${#installed_sys_stream_repos_pkgs[@]} )); then + printf '%s\n' '' \ +'Also to aid the transition from CentOS Stream the following packages will be '\ +'removed from the rpm database but the included repos will be renamed and '\ +'retained but disabled:' \ + "${installed_sys_stream_repos_pkgs[@]}" + fi + + if (( ${#installed_stream_repos_pkgs[@]} )); then + printf '%s\n' '' \ +'Also to aid the transition from CentOS Stream the repos included in the '\ +'following packages will be renamed and retained but disabled:' \ + "${installed_stream_repos_pkgs[@]}" + fi + if (( ${#addl_pkg_removes[@]} )); then - printf '%s\n' '' "In addition to the above the following system packages will be removed:" \ + printf '%s\n' '' \ +"In addition to the above the following system packages will be removed:" \ "${addl_pkg_removes[@]}" fi @@ -661,6 +702,25 @@ package_swaps() { dnfparameters+=( "--setopt=${repo}.gpgkey=file://${gpg_key_file}" ) done + # CentOS Stream specific processing + if (( ${#installed_stream_repos_pkgs[@]} )); then + # Get a list of the repo files. + local -a repos_files + readarray -t repos_files < <( + saferpm -ql "${installed_sys_stream_repos_pkgs[@]}" \ + "${installed_stream_repos_pkgs[@]}" | + grep '^/etc/yum\.repos\.d/.\+\.repo$' + ) + + # Remove the package from the rpm db. + saferpm -e --justdb --nodeps -a "${installed_sys_stream_repos_pkgs[@]}" || + exit_message \ +"Could not remove packages from the rpm db: ${installed_sys_stream_repos_pkgs[@]}" + + # Rename the stream repos with a prefix. + sed -i 's/^\[/['"$stream_prefix"'/' "${repos_files[@]}" + fi + # Use dnf shell to swap the system packages out. safednf -y shell --disablerepo=\* --noautoremove \ --setopt=protected_packages= --setopt=keepcache=True \ @@ -757,7 +817,7 @@ EOF # Distrosync infomsg $'Ensuring repos are enabled before the package swap\n' - safednf -y --enableplugin=config-manager config-manager \ + safednf -y --enableplugin=config_manager config-manager \ --set-enabled "${!repo_map[@]}" || { printf '%s\n' 'Repo name missing?' exit 25 @@ -788,7 +848,7 @@ EOF exit_message "Can't enable modules ${enabled_modules[*]}" fi - # Make sure that excluded repos are disabled. + # Make sure that excluded modules are disabled. infomsg $'Disabling excluded modules\n\n' safednf -y module disable "${module_excludes[@]}" || exit_message "Can't disable modules ${module_excludes[*]}" @@ -796,8 +856,39 @@ EOF infomsg $'\nSyncing packages\n\n' dnf -y distro-sync || exit_message "Error during distro-sync." + # Disable Stream repos. + if (( ${#installed_sys_stream_repos_pkgs[@]} || + ${#installed_stream_repos_pkgs[@]} )); then + dnf -y --enableplugin=config_manager config-manager --set-disabled \ + "$stream_prefix*" || + errmsg \ +$'Failed to disable CentOS Stream repos, please check and disable manually.\n' + + infomsg $'\nCentOS Stream Migration Notes:\n\n' + cat < Date: Sat, 14 Aug 2021 16:32:10 +1200 Subject: [PATCH 4/8] Formatting (#97) * Various formatting and spelling fixes. * Tab to space for more consistent text representation across different editors. --- migrate2rocky/README.md | 2 +- migrate2rocky/migrate2rocky.sh | 784 +++++++++++++++++---------------- 2 files changed, 409 insertions(+), 377 deletions(-) diff --git a/migrate2rocky/README.md b/migrate2rocky/README.md index b20e07f..0f3907a 100644 --- a/migrate2rocky/README.md +++ b/migrate2rocky/README.md @@ -57,7 +57,7 @@ dnf command or the migration. You may safely ignore this message. #### Grub still shows kernel entries from previous installation This is normal. The running kernel cannot be safely removed when migrate2rocky -is run. The RockyLinux kernel should come up as the default highlighed kernel +is run. The RockyLinux kernel should come up as the default highlighted kernel on reboot but the other ones will remain until they are removed or replaced by newer kernels. If you want you can manually remove the old kernels after reboot with dnf or rpm. diff --git a/migrate2rocky/migrate2rocky.sh b/migrate2rocky/migrate2rocky.sh index 744ab7c..081ae5b 100644 --- a/migrate2rocky/migrate2rocky.sh +++ b/migrate2rocky/migrate2rocky.sh @@ -46,7 +46,8 @@ fi # Make sure we're root. if (( EUID != 0 )); then - printf '%s\n' "You must run this script as root. Either use sudo or 'su -c ${0}'" >&2 + printf '%s\n' \ + "You must run this script as root. Either use sudo or 'su -c ${0}'" >&2 exit 1 fi @@ -82,10 +83,10 @@ msg_format () { _var="$1" shift if (( $# > 1 )); then - # shellcheck disable=SC2059 - printf -v "$_var" "$@" + # shellcheck disable=SC2059 + printf -v "$_var" "$@" else - printf -v "$_var" "%s" "$1" + printf -v "$_var" "%s" "$1" fi } @@ -144,23 +145,23 @@ exit_message() { final_message() { errmsg '%s ' \ - "An error occurred while we were attempting to convert your system to" \ - "Rocky Linux. Your system may be unstable. Script will now exit to" \ - "prevent possible damage."$'\n\n' + "An error occurred while we were attempting to convert your system to" \ + "Rocky Linux. Your system may be unstable. Script will now exit to" \ + "prevent possible damage."$'\n\n' logmessage } logmessage(){ printf '%s%s%s\n' "$infocolor" \ - "A log of this installation can be found at $logfile" \ - "$nocolor" >&3 + "A log of this installation can be found at $logfile" \ + "$nocolor" >&3 } # This just grabs a field from os-release and returns it. os-release () ( . /etc/os-release if ! [[ ${!1} ]]; then - return 1 + return 1 fi printf '%s\n' "${!1}" ) @@ -173,7 +174,7 @@ os-release () ( pkg_ver() ( ver=$(rpm -q --qf '%{VERSION}\n' "$1") || return 2 if [[ $(sort -V <<<"$ver"$'\n'"$2" | head -1) != "$2" ]]; then - return 1 + return 1 fi return 0 ) @@ -181,76 +182,84 @@ pkg_ver() ( # Set up a temporary directory. pre_setup () { if ! tmp_dir=$(mktemp -d) || [[ ! -d "$tmp_dir" ]]; then - exit_message "Error creating temp dir" + exit_message "Error creating temp dir" fi # failglob makes pathname expansion fail if empty, dotglob adds files # starting with . to pathname expansion if ( shopt -s failglob dotglob; : "$tmp_dir"/* ) 2>/dev/null ; then - exit_message "Temp dir not empty" + exit_message "Temp dir not empty" fi } # Cleanup function gets rid of the temporary directory. exit_clean () { if [[ -d "$tmp_dir" ]]; then - rm -rf "$tmp_dir" + rm -rf "$tmp_dir" fi if [[ -f "$container_macros" ]]; then - rm -f "$container_macros" + rm -f "$container_macros" fi } pre_check () { if [[ -e /etc/rhsm/ca/katello-server-ca.pem ]]; then - exit_message "Migration from Katello-modified systems is not supported by migrate2rocky. See the README file for details." + exit_message \ +'Migration from Katello-modified systems is not supported by migrate2rocky. '\ +'See the README file for details.' fi if [[ -e /etc/salt/minion.d/susemanager.conf ]]; then - exit_message "Migration from Uyuni/SUSE Manager-modified systems is not supported by migrate2rocky. See the README file for details." + exit_message \ +'Migration from Uyuni/SUSE Manager-modified systems is not supported by '\ +'migrate2rocky. See the README file for details.' fi } # All of the binaries used by this script are available in a EL8 minimal install # and are in /bin, so we should not encounter a system where the script doesn't -# work unless it's severly broken. This is just a simple check that will cause +# work unless it's severely broken. This is just a simple check that will cause # the script to bail if any expected system utilities are missing. bin_check() { # Check the platform. if [[ $(os-release PLATFORM_ID) != "$SUPPORTED_PLATFORM" ]]; then - exit_message "This script must be run on an EL8 distribution. Migration from other distributions is not supported." + exit_message \ +'This script must be run on an EL8 distribution. Migration from other '\ +'distributions is not supported.' fi local -a missing bins bins=( - rpm dnf awk column tee tput mkdir cat arch sort uniq rmdir - rm head curl sha512sum mktemp systemd-detect-virt sed + rpm dnf awk column tee tput mkdir cat arch sort uniq rmdir + rm head curl sha512sum mktemp systemd-detect-virt sed ) if [[ $update_efi ]]; then - bins+=(findmnt grub2-mkconfig efibootmgr grep mokutil lsblk) + bins+=(findmnt grub2-mkconfig efibootmgr grep mokutil lsblk) fi for bin in "${bins[@]}"; do - if ! type "$bin" >/dev/null 2>&1; then - missing+=("$bin") - fi + if ! type "$bin" >/dev/null 2>&1; then + missing+=("$bin") + fi done local -A pkgs pkgs=( - [dnf]=4.2 - [dnf-plugins-core]=0 + [dnf]=4.2 + [dnf-plugins-core]=0 ) for pkg in "${!pkgs[@]}"; do - ver=${pkgs[$pkg]} - if ! pkg_ver "$pkg" "$ver"; then - # shellcheck disable=SC2140 - exit_message \ + ver=${pkgs[$pkg]} + if ! pkg_ver "$pkg" "$ver"; then + # shellcheck disable=SC2140 + exit_message \ "$pkg >= $ver is required for this script. Please run "\ "\"dnf install $pkg; dnf update\" first." - fi + fi done; if (( ${#missing[@]} )); then - exit_message "Commands not found: ${missing[*]}. Possible bad PATH setting or corrupt installation." + exit_message \ +"Commands not found: ${missing[*]}. Possible bad PATH setting or corrupt "\ +"installation." fi } @@ -260,21 +269,21 @@ bin_check() { repoquery () { local name val prev result result=$( - dnf -q --setopt=epel.excludepkgs=epel-release repoquery -i "$1" || - exit_message "Failed to fetch info for package $1." + dnf -q --setopt=epel.excludepkgs=epel-release repoquery -i "$1" || + exit_message "Failed to fetch info for package $1." ) if ! [[ $result ]]; then - # We didn't match this package, the repo could be disabled. - return 1 + # We didn't match this package, the repo could be disabled. + return 1 fi declare -gA repoquery_results=() while IFS=" :" read -r name val; do - if [[ -z $name ]]; then - repoquery_results[$prev]+=" $val" - else - prev=$name - repoquery_results[$name]=$val - fi + if [[ -z $name ]]; then + repoquery_results[$prev]+=" $val" + else + prev=$name + repoquery_results[$name]=$val + fi done <<<"$result" } @@ -283,22 +292,22 @@ repoquery () { repoinfo () { local name val result result=$(dnf -q repoinfo "$1") || - exit_message "Failed to fetch info for repository $1." + exit_message "Failed to fetch info for repository $1." if [[ $result == 'Total packages: 0' ]]; then - # We didn't match this repo. - return 1 + # We didn't match this repo. + return 1 fi declare -gA repoinfo_results=() while IFS=" :" read -r name val; do - if [[ ! ( $name || $val) ]]; then - continue - fi - if [[ -z $name ]]; then - repoinfo_results[$prev]+=" $val" - else - prev=$name - repoinfo_results[$name]=$val - fi + if [[ ! ( $name || $val) ]]; then + continue + fi + if [[ -z $name ]]; then + repoinfo_results[$prev]+=" $val" + else + prev=$name + repoinfo_results[$name]=$val + fi done <<<"$result" # dnf repoinfo doesn't return the gpgkey, but we need that so we have to get @@ -309,21 +318,21 @@ repoinfo () { # of the file. # shellcheck disable=SC2154 repoinfo_results[Repo-gpgkey]=$( - awk ' - $0=="['"${repoinfo_results[Repo-id]}"']",$0=="end_of_file" { - if (l++ < 1) {next} - else if (/^\[.*\]$/) {nextfile} - else if (sub(/^gpgkey\s*=\s*file:\/\//,"")) {print; nextfile} - else {next} - } - ' < "${repoinfo_results[Repo-filename]}" + awk ' + $0=="['"${repoinfo_results[Repo-id]}"']",$0=="end_of_file" { + if (l++ < 1) {next} + else if (/^\[.*\]$/) {nextfile} + else if (sub(/^gpgkey\s*=\s*file:\/\//,"")) {print; nextfile} + else {next} + } + ' < "${repoinfo_results[Repo-filename]}" ) # Add an indicator of whether this is a subscription-manager managed # repository. # shellcheck disable=SC2154 repoinfo_results[Repo-managed]=$( - awk ' + awk ' BEGIN {FS="[)(]"} /^# Managed by \(.*\) subscription-manager$/ {print $2} ' < "${repoinfo_results[Repo-filename]}" @@ -332,28 +341,28 @@ repoinfo () { provides_pkg () ( if [[ ! $1 ]]; then - return 0 + return 0 fi set -o pipefail provides=$(dnf -q provides "$1" | awk '{print $1; nextfile}') || - return 1 + return 1 set +o pipefail pkg=$(rpm -q --queryformat '%{NAME}\n' "$provides") || - pkg=$(dnf -q repoquery --queryformat '%{NAME}\n' "$provides") || - exit_message "Can't get package name for $provides." + pkg=$(dnf -q repoquery --queryformat '%{NAME}\n' "$provides") || + exit_message "Can't get package name for $provides." printf '%s\n' "$pkg" ) # If you pass an empty arg as one of the package specs to rpm it will match -# every package on the system. This funtion simply strips out any empty args +# every package on the system. This function simply strips out any empty args # and passes the rest to rpm to avoid this side-effect. saferpm () ( args=() for a in "$@"; do - if [[ $a ]]; then - args+=("$a") - fi + if [[ $a ]]; then + args+=("$a") + fi done rpm "${args[@]}" ) @@ -362,9 +371,9 @@ saferpm () ( safednf () ( args=() for a in "$@"; do - if [[ $a ]]; then - args+=("$a") - fi + if [[ $a ]]; then + args+=("$a") + fi done dnf "${args[@]}" ) @@ -376,60 +385,62 @@ collect_system_info () { # Check the efi mount first, so we can bail before wasting time on all these # other checks if it's not there. if [[ $update_efi ]]; then - local efi_mount kname - declare -g -a efi_disk efi_partition - efi_mount=$(findmnt --mountpoint /boot/efi --output SOURCE \ - --noheadings) || - exit_message "Can't find EFI mount. No EFI boot detected." - kname=$(lsblk -dno kname "$efi_mount") - efi_disk=$(lsblk -dno pkname "/dev/$kname") + local efi_mount kname + declare -g -a efi_disk efi_partition + efi_mount=$(findmnt --mountpoint /boot/efi --output SOURCE \ + --noheadings) || + exit_message "Can't find EFI mount. No EFI boot detected." + kname=$(lsblk -dno kname "$efi_mount") + efi_disk=$(lsblk -dno pkname "/dev/$kname") - if [[ $efi_disk ]]; then - efi_partition=$(<"/sys/block/$efi_disk/$kname/partition") - else - # This is likely an md-raid or other type of virtual disk, we need - # to dig a little deeper to find the actual physical disks and - # partitions. - kname=$(lsblk -dno kname "$efi_mount") - cd "/sys/block/$kname/slaves" || exit_message \ + if [[ $efi_disk ]]; then + efi_partition=$(<"/sys/block/$efi_disk/$kname/partition") + else + # This is likely an md-raid or other type of virtual disk, we need + # to dig a little deeper to find the actual physical disks and + # partitions. + kname=$(lsblk -dno kname "$efi_mount") + cd "/sys/block/$kname/slaves" || exit_message \ "Unable to gather EFI data: Can't cd to /sys/block/$kname/slaves." - if ! (shopt -s failglob; : ./*) 2>/dev/null; then - exit_message \ + if ! (shopt -s failglob; : ./*) 2>/dev/null; then + exit_message \ "Unable to gather EFI data: No slaves found in /sys/block/$kname/slaves." - fi - efi_disk=() - for d in *; do - efi_disk+=("$(lsblk -dno pkname "/dev/$d")") - efi_partition+=("$(<"$d/partition")") - if [[ ! ${efi_disk[-1]} || ! ${efi_partition[-1]} ]]; then - exit_message \ + fi + efi_disk=() + for d in *; do + efi_disk+=("$(lsblk -dno pkname "/dev/$d")") + efi_partition+=("$(<"$d/partition")") + if [[ ! ${efi_disk[-1]} || ! ${efi_partition[-1]} ]]; then + exit_message \ "Unable to gather EFI data: Can't find disk name or partition number for $d." - fi - done - cd - - fi + fi + done + cd - + fi fi # check if EFI secure boot is enabled if [[ $update_efi ]]; then - if mokutil --sb-state 2>&1 | grep -q "SecureBoot enabled"; then - exit_message "EFI Secure Boot is enabled but Rocky Linux doesn't provide a signed shim yet. Disable EFI Secure Boot and reboot." - fi + if mokutil --sb-state 2>&1 | grep -q "SecureBoot enabled"; then + exit_message \ +"EFI Secure Boot is enabled but Rocky Linux doesn't provide a signed shim yet."\ +" Disable EFI Secure Boot and reboot." + fi fi # Don't enable these module streams, even if they are enabled in the source # distro. declare -g -a module_excludes module_excludes=( - libselinux-python:2.8 + libselinux-python:2.8 ) # Some OracleLinux modules have stream names of ol8 instead of rhel8 and ol # instead of rhel. This is a map that does a glob match and replacement. local -A module_glob_map module_glob_map=( - ['%:ol8']=:rhel8 - ['%:ol']=:rhel + ['%:ol8']=:rhel8 + ['%:ol']=:rhel ); # We need to map rockylinux repository names to the equivalent repositories @@ -440,30 +451,33 @@ collect_system_info () { declare -g -A repo_map pkg_repo_map declare -g -a managed_repos pkg_repo_map=( - [baseos]=rootfiles.noarch - [appstream]=apr-util-ldap.$ARCH - [ha]=pacemaker-doc.noarch - [powertools]=libaec-devel.$ARCH - [extras]=epel-release.noarch + [baseos]=rootfiles.noarch + [appstream]=apr-util-ldap.$ARCH + [ha]=pacemaker-doc.noarch + [powertools]=libaec-devel.$ARCH + [extras]=epel-release.noarch ) -# [devel]=quota-devel.$ARCH +# [devel]=quota-devel.$ARCH PRETTY_NAME=$(os-release PRETTY_NAME) infomsg '%s' \ - "Preparing to migrate $PRETTY_NAME to Rocky Linux 8."$'\n\n' \ - "Determining repository names for $PRETTY_NAME" + "Preparing to migrate $PRETTY_NAME to Rocky Linux 8."$'\n\n' \ + "Determining repository names for $PRETTY_NAME" for r in "${!pkg_repo_map[@]}"; do - printf '.' - p=${pkg_repo_map[$r]} - repoquery "$p" || continue - repo_map[$r]=${repoquery_results[Repository]} + printf '.' + p=${pkg_repo_map[$r]} + repoquery "$p" || continue + repo_map[$r]=${repoquery_results[Repository]} done - printf '%s\n' '' '' "Found the following repositories which map from $PRETTY_NAME to Rocky Linux 8:" - column -t -s $'\t' -N "$PRETTY_NAME,Rocky Linux 8" < <(for r in "${!repo_map[@]}"; do - printf '%s\t%s\n' "${repo_map[$r]}" "$r" - done) + printf '%s\n' '' '' \ +"Found the following repositories which map from $PRETTY_NAME to Rocky Linux 8:" + column -t -s $'\t' -N "$PRETTY_NAME,Rocky Linux 8" < <( + for r in "${!repo_map[@]}"; do + printf '%s\t%s\n' "${repo_map[$r]}" "$r" + done + ) infomsg $'\n'"Getting system package names for $PRETTY_NAME" @@ -477,17 +491,17 @@ collect_system_info () { # system-release here is a bit of a hack, but it ensures that the # rocky-repos package will get installed. for r in "${!repo_map[@]}"; do - repoinfo "${repo_map[$r]}" - if [[ $r == "baseos" ]]; then - local baseos_filename=system-release - if [[ ! ${repoinfo_results[Repo-managed]} ]]; then - baseos_filename="${repoinfo_results[Repo-filename]}" - fi - local baseos_gpgkey="${repoinfo_results[Repo-gpgkey]}" - fi - if [[ ${repoinfo_results[Repo-managed]} ]]; then - managed_repos+=("${repo_map[$r]}") - fi + repoinfo "${repo_map[$r]}" + if [[ $r == "baseos" ]]; then + local baseos_filename=system-release + if [[ ! ${repoinfo_results[Repo-managed]} ]]; then + baseos_filename="${repoinfo_results[Repo-filename]}" + fi + local baseos_gpgkey="${repoinfo_results[Repo-gpgkey]}" + fi + if [[ ${repoinfo_results[Repo-managed]} ]]; then + managed_repos+=("${repo_map[$r]}") + fi done # First get info for the baseos repo @@ -495,160 +509,170 @@ collect_system_info () { declare -g -A pkg_map provides_pkg_map declare -g -a addl_provide_removes addl_pkg_removes provides_pkg_map=( - [rocky-backgrounds]=system-backgrounds - [rocky-indexhtml]=redhat-indexhtml - [rocky-repos]="$baseos_filename" - [rocky-logos]=system-logos - [rocky-logos-httpd]=system-logos-httpd - [rocky-logos-ipa]=system-logos-ipa - [rocky-gpg-keys]="$baseos_gpgkey" - [rocky-release]=system-release + [rocky-backgrounds]=system-backgrounds + [rocky-indexhtml]=redhat-indexhtml + [rocky-repos]="$baseos_filename" + [rocky-logos]=system-logos + [rocky-logos-httpd]=system-logos-httpd + [rocky-logos-ipa]=system-logos-ipa + [rocky-gpg-keys]="$baseos_gpgkey" + [rocky-release]=system-release ) addl_provide_removes=( - redhat-release - redhat-release-eula + redhat-release + redhat-release-eula ) # Check to make sure that we don't already have a full or partial # RockyLinux install. if [[ $(rpm -qa "${!provides_pkg_map[@]}") ]]; then - exit_message \ + exit_message \ $'Found a full or partial RockyLinux install already in place. Aborting\n' $'because continuing with the migration could cause further damage to system.' fi for pkg in "${!provides_pkg_map[@]}"; do - printf '.' - prov=${provides_pkg_map[$pkg]} - pkg_map[$pkg]=$(provides_pkg "$prov") || - exit_message "Can't get package that provides $prov." + printf '.' + prov=${provides_pkg_map[$pkg]} + pkg_map[$pkg]=$(provides_pkg "$prov") || + exit_message "Can't get package that provides $prov." done for prov in "${addl_provide_removes[@]}"; do - printf '.' - local pkg; - pkg=$(provides_pkg "$prov") || continue - addl_pkg_removes+=("$pkg") + printf '.' + local pkg; + pkg=$(provides_pkg "$prov") || continue + addl_pkg_removes+=("$pkg") done - printf '%s\n' '' '' "Found the following system packages which map from $PRETTY_NAME to Rocky Linux 8:" - column -t -s $'\t' -N "$PRETTY_NAME,Rocky Linux 8" < <(for p in "${!pkg_map[@]}"; do - printf '%s\t%s\n' "${pkg_map[$p]}" "$p" - done) + printf '%s\n' '' '' \ +"Found the following system packages which map from $PRETTY_NAME to Rocky "\ +"Linux 8:" + column -t -s $'\t' -N "$PRETTY_NAME,Rocky Linux 8" < <( + for p in "${!pkg_map[@]}"; do + printf '%s\t%s\n' "${pkg_map[$p]}" "$p" + done + ) infomsg $'\n'"Getting list of installed system packages."$'\n' - readarray -t installed_packages < <(saferpm -qa --queryformat="%{NAME}\n" "${pkg_map[@]}") + readarray -t installed_packages < <( + saferpm -qa --queryformat="%{NAME}\n" "${pkg_map[@]}" + ) declare -g -A installed_pkg_check installed_pkg_map for p in "${installed_packages[@]}"; do - installed_pkg_check[$p]=1 + installed_pkg_check[$p]=1 done for p in "${!pkg_map[@]}"; do - if [[ ${pkg_map[$p]} && ${installed_pkg_check[${pkg_map[$p]}]} ]]; then - installed_pkg_map[$p]=${pkg_map[$p]} - fi + if [[ ${pkg_map[$p]} && ${installed_pkg_check[${pkg_map[$p]}]} ]]; then + installed_pkg_map[$p]=${pkg_map[$p]} + fi done; # Special Handling for CentOS Stream Repos installed_sys_stream_repos_pkgs=() installed_stream_repos_pkgs=() for p in "${!stream_repos_pkgs[@]}"; do - if [[ ${installed_pkg_map[$p]} && - ${installed_pkg_map[$p]} == "${stream_repos_pkgs[$p]}" ]] - then - # System package that needs to be swapped / disabled - installed_pkg_map[$p]= - installed_sys_stream_repos_pkgs+=( ${stream_repos_pkgs[$p]} ) - elif rpm --quiet -q "${stream_repos_pkgs[$p]}"; then - # Non-system package, repos just need to be disabled. - installed_stream_repos_pkgs+=( ${stream_repos_pkgs[$p]} ) - fi + if [[ ${installed_pkg_map[$p]} && + ${installed_pkg_map[$p]} == "${stream_repos_pkgs[$p]}" ]] + then + # System package that needs to be swapped / disabled + installed_pkg_map[$p]= + installed_sys_stream_repos_pkgs+=( ${stream_repos_pkgs[$p]} ) + elif rpm --quiet -q "${stream_repos_pkgs[$p]}"; then + # Non-system package, repos just need to be disabled. + installed_stream_repos_pkgs+=( ${stream_repos_pkgs[$p]} ) + fi done - printf '%s\n' '' "We will replace the following $PRETTY_NAME packages with their Rocky Linux 8 equivalents" + printf '%s\n' '' \ +"We will replace the following $PRETTY_NAME packages with their Rocky Linux 8 "\ +"equivalents" column -t -s $'\t' -N "Packages to be Removed,Packages to be Installed" < <( - for p in "${!installed_pkg_map[@]}"; do - printf '%s\t%s\n' "${installed_pkg_map[$p]}" "$p" - done + for p in "${!installed_pkg_map[@]}"; do + printf '%s\t%s\n' "${installed_pkg_map[$p]}" "$p" + done ) if (( ${#installed_sys_stream_repos_pkgs[@]} )); then - printf '%s\n' '' \ + printf '%s\n' '' \ 'Also to aid the transition from CentOS Stream the following packages will be '\ 'removed from the rpm database but the included repos will be renamed and '\ 'retained but disabled:' \ - "${installed_sys_stream_repos_pkgs[@]}" + "${installed_sys_stream_repos_pkgs[@]}" fi if (( ${#installed_stream_repos_pkgs[@]} )); then - printf '%s\n' '' \ + printf '%s\n' '' \ 'Also to aid the transition from CentOS Stream the repos included in the '\ 'following packages will be renamed and retained but disabled:' \ - "${installed_stream_repos_pkgs[@]}" + "${installed_stream_repos_pkgs[@]}" fi if (( ${#addl_pkg_removes[@]} )); then - printf '%s\n' '' \ + printf '%s\n' '' \ "In addition to the above the following system packages will be removed:" \ - "${addl_pkg_removes[@]}" + "${addl_pkg_removes[@]}" fi # Release packages that are part of SIG's should be listed below when they # are available. # UPDATE: We may or may not do something with SIG's here, it could just be - # left as a separate excersize to swap out the sig repos. + # left as a separate exercise to swap out the sig repos. #sigs_to_swap=() infomsg '%s' $'\n' \ - $'Getting a list of enabled modules for the system repositories.\n' + $'Getting a list of enabled modules for the system repositories.\n' # Get a list of system enabled modules. readarray -t enabled_modules < <( - set -e -o pipefail - safednf -q "${repo_map[@]/#/--repo=}" module list --enabled | - awk ' - $1 == "@modulefailsafe", /^$/ {next} - $1 == "Name", /^$/ {if ($1!="Name" && !/^$/) print $1":"$2} - ' | sort -u - set +e +o pipefail + set -e -o pipefail + safednf -q "${repo_map[@]/#/--repo=}" module list --enabled | + awk ' + $1 == "@modulefailsafe", /^$/ {next} + $1 == "Name", /^$/ {if ($1!="Name" && !/^$/) print $1":"$2} + ' | sort -u + set +e +o pipefail ) # Map the known module name differences. disable_modules=() local i gl repl mod for i in "${!enabled_modules[@]}"; do - mod=${enabled_modules[$i]} - for gl in "${!module_glob_map[@]}"; do - repl=${module_glob_map[$gl]} - mod=${mod/$gl/$repl} - done - if [[ $mod != "${enabled_modules[$i]}" ]]; then - disable_modules+=(${enabled_modules[$i]}) - enabled_modules[$i]=$mod - fi + mod=${enabled_modules[$i]} + for gl in "${!module_glob_map[@]}"; do + repl=${module_glob_map[$gl]} + mod=${mod/$gl/$repl} + done + if [[ $mod != "${enabled_modules[$i]}" ]]; then + disable_modules+=(${enabled_modules[$i]}) + enabled_modules[$i]=$mod + fi done # Remove entries matching any excluded modules. if (( ${#module_excludes[@]} )); then - printf '%s\n' '' "Excluding modules:" "${module_excludes[@]}" - local -A module_check='()' - local -a tmparr='()' - for m in "${module_excludes[@]}"; do - module_check[$m]=1 - done - for m in "${enabled_modules[@]}"; do - if [[ ! ${module_check[$m]} ]]; then - tmparr+=("$m") - fi - done - enabled_modules=("${tmparr[@]}") + printf '%s\n' '' "Excluding modules:" "${module_excludes[@]}" + local -A module_check='()' + local -a tmparr='()' + for m in "${module_excludes[@]}"; do + module_check[$m]=1 + done + for m in "${enabled_modules[@]}"; do + if [[ ! ${module_check[$m]} ]]; then + tmparr+=("$m") + fi + done + enabled_modules=("${tmparr[@]}") fi printf '%s\n' '' "Found the following modules to re-enable at completion:" \ - "${enabled_modules[@]}" '' + "${enabled_modules[@]}" '' if (( ${#managed_repos[@]} )); then - printf '%s\n' '' "In addition, since this system uses subscription-manger the following managed repos will be disabled:" \ - "${managed_repos[@]}" + printf '%s\n' '' \ +'In addition, since this system uses subscription-manager the following '\ +'managed repos will be disabled:' \ + "${managed_repos[@]}" fi } @@ -669,11 +693,15 @@ usage() { } >&2 generate_rpm_info() { - mkdir /root/convert - infomsg "Creating a list of RPMs installed: $1"$'\n' - rpm -qa --qf "%{NAME}|%{VERSION}|%{RELEASE}|%{INSTALLTIME}|%{VENDOR}|%{BUILDTIME}|%{BUILDHOST}|%{SOURCERPM}|%{LICENSE}|%{PACKAGER}\n" | sort > "${convert_info_dir}/$HOSTNAME-rpm-list-$1.log" - infomsg "Verifying RPMs installed against RPM database: $1"$'\n\n' - rpm -Va | sort -k3 > "${convert_info_dir}/$HOSTNAME-rpm-list-verified-$1.log" + mkdir /root/convert + infomsg "Creating a list of RPMs installed: $1"$'\n' + rpm -qa --qf \ +"%{NAME}|%{VERSION}|%{RELEASE}|%{INSTALLTIME}|%{VENDOR}|%{BUILDTIME}|"\ +"%{BUILDHOST}|%{SOURCERPM}|%{LICENSE}|%{PACKAGER}\n" | + sort > "${convert_info_dir}/$HOSTNAME-rpm-list-$1.log" + infomsg "Verifying RPMs installed against RPM database: $1"$'\n\n' + rpm -Va | sort -k3 > \ + "${convert_info_dir}/$HOSTNAME-rpm-list-verified-$1.log" } # Run a dnf update before the actual migration. @@ -685,54 +713,55 @@ $'unstable state. Please correct the issues shown here and try again.' } package_swaps() { - # Save off any subscription-manger keys, just in case. + # Save off any subscription-manager keys, just in case. if ( shopt -s failglob dotglob; : "$sm_ca_dir"/* ) 2>/dev/null ; then - tmp_sm_ca_dir=$tmp_dir/sm-certs - mkdir "$tmp_sm_ca_dir" || - exit_message "Could not create directory: $tmp_sm_ca_dir" - cp -f -dR --preserve=all "$sm_ca_dir"/* "$tmp_sm_ca_dir/" || - exit_message "Could not copy certs to $tmp_sm_ca_dir" + tmp_sm_ca_dir=$tmp_dir/sm-certs + mkdir "$tmp_sm_ca_dir" || + exit_message "Could not create directory: $tmp_sm_ca_dir" + cp -f -dR --preserve=all "$sm_ca_dir"/* "$tmp_sm_ca_dir/" || + exit_message "Could not copy certs to $tmp_sm_ca_dir" fi # prepare repo parameters local -a dnfparameters for repo in "${!repo_urls[@]}"; do - dnfparameters+=( "--repofrompath=${repo},${repo_urls[${repo}]}" ) - dnfparameters+=( "--setopt=${repo}.gpgcheck=1" ) - dnfparameters+=( "--setopt=${repo}.gpgkey=file://${gpg_key_file}" ) + dnfparameters+=( "--repofrompath=${repo},${repo_urls[${repo}]}" ) + dnfparameters+=( "--setopt=${repo}.gpgcheck=1" ) + dnfparameters+=( "--setopt=${repo}.gpgkey=file://${gpg_key_file}" ) done # CentOS Stream specific processing if (( ${#installed_stream_repos_pkgs[@]} )); then - # Get a list of the repo files. - local -a repos_files - readarray -t repos_files < <( - saferpm -ql "${installed_sys_stream_repos_pkgs[@]}" \ - "${installed_stream_repos_pkgs[@]}" | - grep '^/etc/yum\.repos\.d/.\+\.repo$' - ) + # Get a list of the repo files. + local -a repos_files + readarray -t repos_files < <( + saferpm -ql "${installed_sys_stream_repos_pkgs[@]}" \ + "${installed_stream_repos_pkgs[@]}" | + grep '^/etc/yum\.repos\.d/.\+\.repo$' + ) - # Remove the package from the rpm db. - saferpm -e --justdb --nodeps -a "${installed_sys_stream_repos_pkgs[@]}" || - exit_message \ + # Remove the package from the rpm db. + saferpm -e --justdb --nodeps -a "${installed_sys_stream_repos_pkgs[@]}" || + exit_message \ "Could not remove packages from the rpm db: ${installed_sys_stream_repos_pkgs[@]}" - # Rename the stream repos with a prefix. - sed -i 's/^\[/['"$stream_prefix"'/' "${repos_files[@]}" + # Rename the stream repos with a prefix. + sed -i 's/^\[/['"$stream_prefix"'/' "${repos_files[@]}" fi # Use dnf shell to swap the system packages out. safednf -y shell --disablerepo=\* --noautoremove \ - --setopt=protected_packages= --setopt=keepcache=True \ - "${dnfparameters[@]}" \ - </dev/null - )]=$rpm - done + # Get a list of rpm packages to package names + local -A rpm_map + local -a file_list + for rpm in /var/cache/dnf/{rockybaseos,rockyappstream}-*/packages/*.rpm + do + rpm_map[$( + rpm -q --qf '%{NAME}\n' --nodigest "$rpm" 2>/dev/null + )]=$rpm + done - # Attempt to install. - for pkg in "${check_installed[@]}"; do - printf '%s\n' "$pkg" - if ! rpm -i --force --nodeps --nodigest "${rpm_map[$pkg]}" \ - 2>/dev/null; then - # Try to install the package in just the db, then clean it up. - rpm -i --force --justdb --nodeps --nodigest "${rpm_map[$pkg]}" \ - 2>/dev/null + # Attempt to install. + for pkg in "${check_installed[@]}"; do + printf '%s\n' "$pkg" + if ! rpm -i --force --nodeps --nodigest "${rpm_map[$pkg]}" \ + 2>/dev/null; then + # Try to install the package in just the db, then clean it up. + rpm -i --force --justdb --nodeps --nodigest "${rpm_map[$pkg]}" \ + 2>/dev/null - # Get list of files that are still causing problems and donk - # them. - readarray -t file_list < <( - rpm -V "$pkg" 2>/dev/null | awk '$1!="missing" {print $2}' - ) - for file in "${file_list[@]}"; do - rmdir "$file" || - rm -f "$file" || - rm -rf "$file" - done + # Get list of files that are still causing problems and donk + # them. + readarray -t file_list < <( + rpm -V "$pkg" 2>/dev/null | awk '$1!="missing" {print $2}' + ) + for file in "${file_list[@]}"; do + rmdir "$file" || + rm -f "$file" || + rm -rf "$file" + done - # Now try re-installing the package to replace the missing - # files. Regardless of the outcome here we just accept it and - # move on and hope for the best. - rpm -i --reinstall --force --nodeps --nodigest \ - "${rpm_map[$pkg]}" 2>/dev/null - fi - done + # Now try re-installing the package to replace the missing + # files. Regardless of the outcome here we just accept it and + # move on and hope for the best. + rpm -i --reinstall --force --nodeps --nodigest \ + "${rpm_map[$pkg]}" 2>/dev/null + fi + done fi # Distrosync infomsg $'Ensuring repos are enabled before the package swap\n' - safednf -y --enableplugin=config_manager config-manager \ - --set-enabled "${!repo_map[@]}" || { - printf '%s\n' 'Repo name missing?' - exit 25 + safednf -y --enableplugin=config-manager config-manager \ + --set-enabled "${!repo_map[@]}" || { + printf '%s\n' 'Repo name missing?' + exit 25 } if (( ${#managed_repos[@]} )); then - # Filter the managed repos for ones still in the system. - readarray -t managed_repos < <( - safednf -q repolist "${managed_repos[@]}" | awk '$1!="repo" {print $1}' - ) + # Filter the managed repos for ones still in the system. + readarray -t managed_repos < <( + safednf -q repolist "${managed_repos[@]}" | + awk '$1!="repo" {print $1}' + ) - if (( ${#managed_repos[@]} )); then - infomsg $'\nDisabling subscription managed repos\n' - safednf -y --enableplugin=config-manager config-manager \ - --disable "${managed_repos[@]}" - fi + if (( ${#managed_repos[@]} )); then + infomsg $'\nDisabling subscription managed repos\n' + safednf -y --enableplugin=config-manager config-manager \ + --disable "${managed_repos[@]}" + fi fi if (( ${#disable_modules[@]} )); then - infomsg $'Disabling modules\n\n' - safednf -y module disable "${disable_modules[@]}" || - exit_message "Can't disable modules ${disable_modules[*]}" + infomsg $'Disabling modules\n\n' + safednf -y module disable "${disable_modules[@]}" || + exit_message "Can't disable modules ${disable_modules[*]}" fi if (( ${#enabled_modules[@]} )); then - infomsg $'Enabling modules\n\n' - safednf -y module enable "${enabled_modules[@]}" || - exit_message "Can't enable modules ${enabled_modules[*]}" + infomsg $'Enabling modules\n\n' + safednf -y module enable "${enabled_modules[@]}" || + exit_message "Can't enable modules ${enabled_modules[*]}" fi # Make sure that excluded modules are disabled. infomsg $'Disabling excluded modules\n\n' safednf -y module disable "${module_excludes[@]}" || - exit_message "Can't disable modules ${module_excludes[*]}" + exit_message "Can't disable modules ${module_excludes[*]}" infomsg $'\nSyncing packages\n\n' dnf -y distro-sync || exit_message "Error during distro-sync." # Disable Stream repos. if (( ${#installed_sys_stream_repos_pkgs[@]} || - ${#installed_stream_repos_pkgs[@]} )); then - dnf -y --enableplugin=config_manager config-manager --set-disabled \ - "$stream_prefix*" || - errmsg \ + ${#installed_stream_repos_pkgs[@]} )); then + dnf -y --enableplugin=config_manager config-manager --set-disabled \ + "$stream_prefix*" || + errmsg \ $'Failed to disable CentOS Stream repos, please check and disable manually.\n' - infomsg $'\nCentOS Stream Migration Notes:\n\n' - cat < "$container_macros" + declare -g container_macros + container_macros=$(mktemp /etc/rpm/macros.zXXXXXX) + printf '%s\n' '%_netsharedpath /sys:/proc' > "$container_macros" elif [[ -d /sys/firmware/efi/ ]]; then - declare -g update_efi - update_efi=true + declare -g update_efi + update_efi=true fi } # Called to update the EFI boot. fix_efi () ( grub2-mkconfig -o /boot/efi/EFI/rocky/grub.cfg || - exit_message "Error updating the grub config." + exit_message "Error updating the grub config." for i in "${!efi_disk[@]}"; do - efibootmgr -c -d "/dev/${efi_disk[$i]}" -p "${efi_partition[$i]}" \ - -L "Rocky Linux" -l /EFI/rocky/grubx64.efi || - exit_message "Error updating uEFI firmware." + efibootmgr -c -d "/dev/${efi_disk[$i]}" -p "${efi_partition[$i]}" \ + -L "Rocky Linux" -l /EFI/rocky/grubx64.efi || + exit_message "Error updating uEFI firmware." done ) # Download and verify the Rocky Linux package signing key establish_gpg_trust () { - # create temp dir and verify it is really created and empty, so we are sure deleting it afterwards won't cause any harm + # create temp dir and verify it is really created and empty, so we are sure + # deleting it afterwards won't cause any harm declare -g gpg_tmp_dir gpg_tmp_dir=$tmp_dir/gpg if ! mkdir "$gpg_tmp_dir" || [[ ! -d "$gpg_tmp_dir" ]]; then - exit_message "Error creating temp dir" + exit_message "Error creating temp dir" fi - # failglob makes pathname expansion fail if empty, dotglob adds files starting with . to pathname expansion + # failglob makes pathname expansion fail if empty, dotglob adds files + # starting with . to pathname expansion if ( shopt -s failglob dotglob; : "$gpg_tmp_dir"/* ) 2>/dev/null ; then - exit_message "Temp dir not empty" + exit_message "Temp dir not empty" fi # extract the filename from the url, use the temp dir just created declare -g gpg_key_file="$gpg_tmp_dir/${gpg_key_url##*/}" if ! curl -L -o "$gpg_key_file" --silent --show-error "$gpg_key_url"; then - rm -rf "$gpg_tmp_dir" - exit_message "Error downloading the Rocky Linux signing key." + rm -rf "$gpg_tmp_dir" + exit_message "Error downloading the Rocky Linux signing key." fi if ! sha512sum --quiet -c <<<"$gpg_key_sha512 $gpg_key_file"; then - rm -rf "$gpg_tmp_dir" - exit_message "Error validating the signing key." + rm -rf "$gpg_tmp_dir" + exit_message "Error validating the signing key." fi } From 33373b4ef487b902413325769d734a54a7e58a16 Mon Sep 17 00:00:00 2001 From: Peter Ajamian Date: Sat, 14 Aug 2021 16:37:40 +1200 Subject: [PATCH 5/8] Use C locale instead of en_US (#98) en_US is not guaranteed to be installed on all systems, but C is, so we use the C locale to guarantee that all the dnf and rpm command output parses properly. --- migrate2rocky/migrate2rocky.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/migrate2rocky/migrate2rocky.sh b/migrate2rocky/migrate2rocky.sh index 081ae5b..14cb4c0 100644 --- a/migrate2rocky/migrate2rocky.sh +++ b/migrate2rocky/migrate2rocky.sh @@ -106,7 +106,8 @@ errmsg () { printf '%s%s%s' "$errcolor" "$msg" "$nocolor" >&4 } -export LC_ALL=en_US.UTF-8 LANGUAGE=en_US +export LC_ALL=C.UTF-8 +unset LANGUAGE shopt -s nullglob SUPPORTED_MAJOR="8" From f5e7738c687bae9275848d63ef0cb2f57b27e72e Mon Sep 17 00:00:00 2001 From: Peter Ajamian Date: Sat, 14 Aug 2021 19:43:15 +1200 Subject: [PATCH 6/8] Document issue with disappearing SIG repos --- migrate2rocky/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/migrate2rocky/README.md b/migrate2rocky/README.md index 0f3907a..4151cdd 100644 --- a/migrate2rocky/README.md +++ b/migrate2rocky/README.md @@ -83,6 +83,18 @@ fix this issue run the following command after migration: ipa-server-upgrade --skip-version-check ``` +#### CentOS SIG repositories disappear after migrating to RockyLinux. + +This is because the centos-release-* packages that contain the .repo files for +the individual repositories depend on centos-release. Storage sig and related +release packages should be available soon from RockyLinux. In the meantine you +can use a command like the following to install the .repo files and continue to +use the repository from CentOS (note please substitute the URL to the release +package for the repo that you need): +``` +rpm2cpio <(curl http://mirror.centos.org/centos/8/extras/x86_64/os/Packages/centos-release-gluster9-1.0-1.el8.noarch.rpm) | cpio -iD/ \*.repo +``` + ### Latest Version The latest version of this script can be found [here](https://github.com/rocky-linux/rocky-tools/). From 142ce12645fc914f8c1e92cb555c1d0afb18b43b Mon Sep 17 00:00:00 2001 From: Peter Ajamian Date: Sat, 14 Aug 2021 20:07:35 +1200 Subject: [PATCH 7/8] Add note about mitigating Java alternatives issue before IPA issue. ipa-server-upgrade is a java program, and as such is subject to the issue with Java alternatives mentioned earlier in Known Issues. Add a note to reference mitigating the issue with Java alternatives before attempting to run ipa-server-upgrade. --- migrate2rocky/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/migrate2rocky/README.md b/migrate2rocky/README.md index 4151cdd..25530d7 100644 --- a/migrate2rocky/README.md +++ b/migrate2rocky/README.md @@ -82,6 +82,9 @@ fix this issue run the following command after migration: ``` ipa-server-upgrade --skip-version-check ``` +> Note: Since ipa-server-upgrade is a java program you will likely have to run +> the command to mitigate the "Symbolic links to Java programs..." issue above +> before running this command. #### CentOS SIG repositories disappear after migrating to RockyLinux. From d7e4c072a2b03f4f457d46fbe3a2f65ec5bd214b Mon Sep 17 00:00:00 2001 From: Peter Ajamian Date: Sun, 15 Aug 2021 20:39:26 +1200 Subject: [PATCH 8/8] dnf should always assume yes (#102) There are cases where dnf might wait for confirmation, sometimes for a missing key, etc, that one would not expect. By always passing "-y" we ensure this isn't an issue. --- migrate2rocky/migrate2rocky.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/migrate2rocky/migrate2rocky.sh b/migrate2rocky/migrate2rocky.sh index 14cb4c0..cdf3616 100644 --- a/migrate2rocky/migrate2rocky.sh +++ b/migrate2rocky/migrate2rocky.sh @@ -270,7 +270,7 @@ bin_check() { repoquery () { local name val prev result result=$( - dnf -q --setopt=epel.excludepkgs=epel-release repoquery -i "$1" || + dnf -y -q --setopt=epel.excludepkgs=epel-release repoquery -i "$1" || exit_message "Failed to fetch info for package $1." ) if ! [[ $result ]]; then @@ -292,7 +292,7 @@ repoquery () { # info for the resulting repository. repoinfo () { local name val result - result=$(dnf -q repoinfo "$1") || + result=$(dnf -y -q repoinfo "$1") || exit_message "Failed to fetch info for repository $1." if [[ $result == 'Total packages: 0' ]]; then # We didn't match this repo. @@ -346,11 +346,11 @@ provides_pkg () ( fi set -o pipefail - provides=$(dnf -q provides "$1" | awk '{print $1; nextfile}') || + provides=$(dnf -y -q provides "$1" | awk '{print $1; nextfile}') || return 1 set +o pipefail pkg=$(rpm -q --queryformat '%{NAME}\n' "$provides") || - pkg=$(dnf -q repoquery --queryformat '%{NAME}\n' "$provides") || + pkg=$(dnf -y -q repoquery --queryformat '%{NAME}\n' "$provides") || exit_message "Can't get package name for $provides." printf '%s\n' "$pkg" ) @@ -627,7 +627,7 @@ $'because continuing with the migration could cause further damage to system.' # Get a list of system enabled modules. readarray -t enabled_modules < <( set -e -o pipefail - safednf -q "${repo_map[@]/#/--repo=}" module list --enabled | + safednf -y -q "${repo_map[@]/#/--repo=}" module list --enabled | awk ' $1 == "@modulefailsafe", /^$/ {next} $1 == "Name", /^$/ {if ($1!="Name" && !/^$/) print $1":"$2} @@ -856,7 +856,7 @@ EOF if (( ${#managed_repos[@]} )); then # Filter the managed repos for ones still in the system. readarray -t managed_repos < <( - safednf -q repolist "${managed_repos[@]}" | + safednf -y -q repolist "${managed_repos[@]}" | awk '$1!="repo" {print $1}' )