diff --git a/migrate2rocky/migrate2rocky.sh b/migrate2rocky/migrate2rocky.sh index a61c446..6213ec7 100644 --- a/migrate2rocky/migrate2rocky.sh +++ b/migrate2rocky/migrate2rocky.sh @@ -56,16 +56,53 @@ fi logfile=/var/log/migrate2rocky.log # Send all output to the logfile as well as stdout. +# After the following we get: +# Output to 1 goes to stdout and the logfile. +# Output to 2 goes to stderr and the logfile. +# Output to 3 just goes to stdout. +# Output to 4 just goes to stderr. +# Output to 5 just goes to the logfile. truncate -s0 "$logfile" -exec > >(tee -a "$logfile") 2> >(tee -a "$logfile" >&2) +exec \ + 3>&1 \ + 4>&2 \ + 5>> "$logfile" \ + > >(tee -a "$logfile") \ + 2> >(tee -a "$logfile" >&2) # List nocolor last here so that -x doesn't bork the display. -#errcolor=$(tput setaf 1) -#blue=$(tput setaf 4) -#nocolor=$(tput op) -errcolor= -blue= -nocolor= +errcolor=$(tput setaf 1) +infocolor=$(tput setaf 6) +nocolor=$(tput op) + +# Single arg just gets returned verbatim, multi arg gets formatted via printf. +# First arg is the name of a variable to store the results. +msg_format () { + local _var + _var="$1" + shift + if (( $# > 1 )); then + printf -v "$_var" "$@" + else + printf -v "$_var" "%s" "$1" + fi +} + +# Send an info message to the log file and stdout (with color) +infomsg () { + local msg + msg_format msg "$@" + printf '%s' "$msg" >&5 + printf '%s%s%s' "$infocolor" "$msg" "$nocolor" >&3 +} + +# Send an error message to the log file and stderr (with color) +errmsg () { + local msg + msg_format msg "$@" + printf '%s' "$msg" >&5 + printf '%s%s%s' "$errcolor" "$msg" "$nocolor" >&4 +} export LANG=en_US.UTF-8 shopt -s nullglob @@ -77,6 +114,9 @@ ARCH=$(arch) gpg_key_url="https://dl.rockylinux.org/pub/rocky/RPM-GPG-KEY-rockyofficial" gpg_key_sha512="88fe66cf0a68648c2371120d56eb509835266d9efdf7c8b9ac8fc101bdf1f0e0197030d3ea65f4b5be89dc9d1ef08581adb068815c88d7b1dc40aa1c32990f6a" +sm_ca_dir=/etc/rhsm/ca +unset tmp_sm_ca_dir + # all repos must be signed with the same key given in $gpg_key_url declare -A repo_urls repo_urls=( @@ -87,18 +127,23 @@ repo_urls=( unset CDPATH exit_message() { - printf '%s\n' "$1" + errmsg $'\n'"$1"$'\n\n' final_message exit 1 -} >&2 +} final_message() { - printf '%s\n' "${errcolor}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.$nocolor" - logmessage + 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' + logmessage } logmessage(){ - printf '%s\n' "${blue}A log of this installation can be found at $logfile$nocolor" + printf '%s%s%s\n' "$infocolor" \ + "A log of this installation can be found at $logfile" \ + "$nocolor" >&3 } # This just grabs a field from os-release and returns it. @@ -123,6 +168,25 @@ pkg_ver() ( return 0 ) +# Set up a temporary directory. +pre_setup () { + if ! tmp_dir=$(mktemp -d) || [[ ! -d "$tmp_dir" ]]; then + 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" + fi +} + +# Cleanup function gets rid of the temporary directory. +exit_clean () { + if [[ -d "$tmp_dir" ]]; then + rm -rf "$tmp_dir" + 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." @@ -314,8 +378,9 @@ collect_system_info () { # [devel]=quota-devel.$ARCH PRETTY_NAME=$(os-release PRETTY_NAME) - printf '%s\n' "${blue}Preparing to migrate $PRETTY_NAME to Rocky Linux 8.$nocolor" - printf '\n%s' "${blue}Determining repository names for $PRETTY_NAME$nocolor" + infomsg '%s' \ + "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 '.' @@ -329,7 +394,7 @@ collect_system_info () { printf '%s\t%s\n' "${repo_map[$r]}" "$r" done) - printf '\n%s' "${blue}Getting system package names for $PRETTY_NAME$nocolor." + infomsg $'\n'"Getting system package names for $PRETTY_NAME" # We don't know what the names of these packages are, we have to discover # them via various means. The most common means is to look for either a @@ -388,7 +453,7 @@ collect_system_info () { printf '%s\t%s\n' "${pkg_map[$p]}" "$p" done) - printf '%s\n' '' "${blue}Getting list of installed system packages$nocolor." + infomsg $'\n'"Getting list of installed system packages."$'\n' readarray -t installed_packages < <(saferpm -qa --queryformat="%{NAME}\n" "${pkg_map[@]}") declare -g -A installed_pkg_check installed_pkg_map @@ -419,7 +484,8 @@ collect_system_info () { # left as a separate excersize to swap out the sig repos. #sigs_to_swap=() - printf '%s\n' '' "${blue}Getting a list of enabled modules for the system repositories$nocolor." + infomsg '%s' $'\n' \ + $'Getting a list of enabled modules for the system repositories.\n' # Get a list of system enabled modules. readarray -t enabled_modules < <( @@ -473,13 +539,22 @@ usage() { generate_rpm_info() { mkdir /root/convert - printf '%s\n' "${blue}Creating a list of RPMs installed: $1$nocolor" + 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" - printf '%s\n' "${blue}Verifying RPMs installed against RPM database: $1$nocolor" '' + infomsg "Verifying RPMs installed against RPM database: $1"$'\n\n' rpm -Va | sort -k3 > "${convert_info_dir}/$HOSTNAME-rpm-list-verified-$1.log" } package_swaps() { + # Save off any subscription-manger 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" + fi + # prepare repo parameters local -a dnfparameters for repo in "${!repo_urls[@]}"; do @@ -516,7 +591,9 @@ EOF ) if (( ${#check_removed[@]} )); then - printf '%s\n' '' "${blue}Packages found on system that should still be removed. Forcibly removing them with rpm:$nocolor" + infomsg '%s' $'\n' \ + "Packages found on system that should still be removed. Forcibly" \ + " removing them with rpm:"$'\n' # Removed packages still found on the system. Forcibly remove them. for pkg in "${check_removed[@]}"; do # Extra safety measure, skip if empty string @@ -537,7 +614,9 @@ EOF } | sort | uniq -u ) if (( ${#check_installed[@]} )); then - printf '%s\n' '' "${blue}Some required packages were not installed by dnf. Attempting to force with rpm:$nocolor" + infomsg '%s' $'\n' \ + "Some required packages were not installed by dnf. Attempting to" \ + " force with rpm:"$'\n' # Get a list of rpm packages to package names local -A rpm_map @@ -579,9 +658,9 @@ EOF fi # Distrosync - printf '%s\n' '' "${blue}Removing dnf cache$nocolor" + infomsg $'\nRemoving dnf cache\n' rm -rf /var/cache/{yum,dnf} - printf '%s\n' "${blue}Ensuring repos are enabled before the package swap$nocolor" + infomsg $'Ensuring repos are enabled before the package swap\n' safednf -y config-manager --set-enabled "${!repo_map[@]}" || { printf '%s\n' 'Repo name missing?' exit 25 @@ -594,24 +673,70 @@ EOF ) if (( ${#managed_repos[@]} )); then - printf '%s\n' '' "${blue}Disabling subscription managed repos$nocolor." + infomsg $'\nDisabling subscription managed repos\n' safednf -y config-manager --disable "${managed_repos[@]}" fi fi if (( ${#enabled_modules[@]} )); then - printf '%s\n' "${blue}Enabling modules$nocolor" '' + infomsg $'Enabling modules\n\n' safednf -y module enable "${enabled_modules[@]}" || exit_message "Can't enable modules ${enabled_modules[*]}" fi # Make sure that excluded repos are disabled. - printf '%s\n' "${blue}Disabling excluded modules$nocolor" '' + infomsg $'Disabling excluded modules\n\n' safednf -y module disable "${module_excludes[@]}" || exit_message "Can't disable modules ${module_excludes[*]}" - printf '%s\n' '' "${blue}Syncing packages$nocolor" '' + infomsg $'\nSyncing packages\n\n' dnf -y distro-sync || exit_message "Error during distro-sync." + + if rpm --quiet -q subscription-manager; then + infomsg $'Subscription Manager found on system.\n' + cat <