Linux evo.fastest-server.com 5.14.0-284.1101.el9.tuxcare.11.els11.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Aug 14 13:30:35 UTC 2026 x86_64
LiteSpeed
Server IP : 103.249.112.113 & Your IP : 216.73.217.135
Domains : 988 Domain
User : tanishks
Terminal
Auto Root
Create File
Create Folder
Localroot Suggester
Backdoor Destroyer
Readme
/
home /
Delete
Unzip
Name
Size
Permission
Date
Action
.cpan
[ DIR ]
drwxr-xr-x
2026-09-04 11:35
.cpanm
[ DIR ]
drwxr-xr-x
2026-09-04 11:37
.cpcpan
[ DIR ]
drwx------
2026-09-04 10:29
amplecoi
[ DIR ]
drwx--x--x
2026-04-20 06:38
apperweb
[ DIR ]
drwx--x--x
2026-08-17 09:27
aryasdan
[ DIR ]
drwx--x--x
2026-04-20 06:38
atozserv
[ DIR ]
drwx--x--x
2026-05-08 10:52
aztutori
[ DIR ]
drwx--x--x
2026-04-20 06:38
bubundas
[ DIR ]
drwx--x--x
2026-06-26 06:42
buildsdc
[ DIR ]
drwx--x--x
2026-04-20 06:41
cPanelInstall
[ DIR ]
drwxr-xr-x
2026-09-04 10:39
cforcatm
[ DIR ]
drwx--x--x
2026-04-20 06:38
coderare
[ DIR ]
drwx--x--x
2026-04-20 06:38
comunica
[ DIR ]
drwx--x--x
2026-04-20 06:41
cvlivein
[ DIR ]
drwx--x--x
2026-04-20 06:38
cwdoffic
[ DIR ]
drwx--x--x
2026-04-20 06:38
democpanel
[ DIR ]
drwx--x--x
2026-04-20 06:38
digibaza
[ DIR ]
drwx--x--x
2026-04-20 06:38
djmazza
[ DIR ]
drwx--x--x
2026-04-20 06:38
dogemyid
[ DIR ]
drwx--x--x
2026-04-20 06:38
educationworkcen
[ DIR ]
drwx--x--x
2026-04-20 06:38
eimugurtebackup
[ DIR ]
drwx--x--x
2026-04-20 06:38
englishaajbikel
[ DIR ]
drwx--x--x
2026-04-20 06:38
exindia
[ DIR ]
drwx--x--x
2026-04-20 06:38
fastestserver
[ DIR ]
drwx--x--x
2026-04-20 06:38
gplfree
[ DIR ]
drwx--x--x
2026-04-20 06:38
greenworld
[ DIR ]
drwx--x--x
2026-04-20 06:38
hagoid
[ DIR ]
drwx--x--x
2026-04-20 06:38
hglkjklgkjjh
[ DIR ]
drwx--x--x
2026-04-20 06:38
howrahhaat
[ DIR ]
drwx--x--x
2026-04-20 06:38
jbscitymall
[ DIR ]
drwx--x--x
2026-04-20 06:38
jupiiter
[ DIR ]
drwx--x--x
2026-04-20 06:38
krishnac
[ DIR ]
drwx--x--x
2026-04-20 06:38
litespeedv2easyc
[ DIR ]
drwx--x--x
2026-04-20 06:38
msmxtend
[ DIR ]
drwx--x--x
2026-04-20 06:38
news4thcolumn
[ DIR ]
drwx--x--x
2026-04-20 06:38
newsapp
[ DIR ]
drwx--x--x
2026-04-20 06:38
offroadtourandtr
[ DIR ]
drwx--x--x
2026-04-20 06:38
oscdnscalewithus
[ DIR ]
drwx--x--x
2026-09-05 08:30
quickmar
[ DIR ]
drwx--x--x
2026-04-20 06:38
saint
[ DIR ]
drwx--x--x
2026-04-20 06:38
scalewithus
[ DIR ]
drwx--x--x
2026-04-20 06:38
scripts1
[ DIR ]
drwx--x--x
2026-04-20 06:38
sitepadeasyconfi
[ DIR ]
drwx--x--x
2026-04-20 06:38
smsartsandscienc
[ DIR ]
drwx--x--x
2026-09-05 08:30
snowdrop
[ DIR ]
drwx--x--x
2026-07-20 20:50
softaculouseasyc
[ DIR ]
drwx--x--x
2026-04-20 06:38
solidfor
[ DIR ]
drwx--x--x
2026-04-20 06:38
srtexpo1
[ DIR ]
drwx--x--x
2026-04-20 06:38
super
[ DIR ]
drwx--x--x
2026-04-20 06:42
tanishks
[ DIR ]
drwx--x--x
2026-05-25 19:31
techieyc
[ DIR ]
drwx--x--x
2026-09-05 15:08
tempmail
[ DIR ]
drwx--x--x
2026-04-20 06:38
tersantu
[ DIR ]
drwx--x--x
2026-04-20 06:38
trawebsm
[ DIR ]
drwx--x--x
2026-04-20 06:38
virtfs
[ DIR ]
drwx--x--x
2026-09-04 10:36
wpnull
[ DIR ]
drwx--x--x
2026-04-20 06:38
wpnulltech
[ DIR ]
drwx--x--x
2026-04-20 06:38
xbabexyz
[ DIR ]
drwx--x--x
2026-04-20 06:38
0_README_BEFORE_DELETING_VIRTFS
530
B
-rw-r--r--
2026-09-04 10:28
cldeploy
164.09
KB
-rw-r--r--
2026-09-04 11:26
latest
72.49
KB
-rw-r--r--
2026-09-04 09:49
Save
Rename
#!/bin/bash # Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2023 All Rights Reserved # # Licensed under CLOUD LINUX LICENSE AGREEMENT # http://cloudlinux.com/docs/LICENSE.TXT ## centos2cl INFO # Short Description :upgrades CentOS or RHEL distro to CloudLinux # Description :removes yum repo configuration related to CentOS/RHEL, # as well as release related packages. Installs cloudlinux # release related packages, new kernel and lve tools ## centos2cl INFO version="1.132" # Use field-based parsing instead of character-based to support multi-digit versions (10, 11, etc.) cut -c 1 fails for # "10.0" (returns "1"), cut -d. -f1 correctly returns "10" OS_VERSION="$(rpm -q --qf '%{version}' $(rpm -q --whatprovides redhat-release 2>/dev/null) 2>/dev/null | cut -d. -f1)" OS_RELEASE="$(rpm -q --qf '%{version}' $(rpm -q --whatprovides redhat-release 2>/dev/null) 2>/dev/null | cut -d. -f2)" if [[ -z "$OS_RELEASE" && -e /etc/redhat-release && "$OS_VERSION" -eq "7" ]]; then OS_RELEASE="$(grep -oP "7.\d+" /etc/redhat-release | cut -c 3-)" fi LOWER_VERSION_RELEASE=$(echo "$OS_VERSION.$OS_RELEASE" | /bin/awk -F "." 'BEGIN { OFS = "." } {print $1,$2-1}') INSTALL_LOWER_VERSION=false BACKUP="/etc/cl-convert-saved" CL_SOLO_META_PACKAGE="cloudlinux-solo-meta" CL_ADMIN_META_PACKAGE="cloudlinux-admin-meta" CL_CONTAINER_META_PACKAGE="cloudlinux-container" BOOT_STACK_PACKAGES="shim* fwupd* fwupdate* grub2*" ROLLOUT_WARNING_FILTER="forced skip_if_unavailable" OPEN_VZ_MARKER="/proc/vz/vestat" # Reject externally-supplied repo URLs / build IDs / auth tokens that carry # shell metacharacters before they are interpolated into the command strings # run by retry_wrapper's `/bin/bash -c`. Defined early so CURRENT_REPO_URL (set # from the environment just below) and the getopt handlers can all fail closed # through one validator. $1 = kind (repo-url|build-id|auth-token), $2 = name # for the error message, $3 = value. validate_external_input() { local kind="$1" name="$2" value="$3" pattern case "$kind" in repo-url) pattern='^https?://[A-Za-z0-9._~:/?#@%=+,-]+$' ;; build-id) pattern='^[0-9a-zA-Z]+$' ;; # alphanumeric build-system hash (e.g. 24-hex ObjectId), not just numeric auth-token) pattern='^[A-Za-z0-9._+/=-]+$' ;; *) echo "validate_external_input: unknown kind '$kind'" >&2; exit 1 ;; esac if [[ ! "$value" =~ $pattern ]]; then echo "cldeploy: error - $name contains disallowed characters" >&2 exit 1 fi } ALMALINUX_REPO_URL="https://repo.almalinux.org" PUBLIC_REPO_URL="https://repo.cloudlinux.com" # CURRENT_REPO_URL can be changed by setting this enviroment variable CURRENT_REPO_URL="${CURRENT_REPO_URL:-$PUBLIC_REPO_URL}" validate_external_input repo-url "CURRENT_REPO_URL" "${CURRENT_REPO_URL}" PYTHON_BIN="/usr/bin/python3" if [[ ! -f "$PYTHON_BIN" ]]; then PYTHON_BIN="/usr/bin/python" fi ARGS=$* init_vars() { # the files below are also used in script 'cldeploy-precheck' script in 'cpanel-lvemanager' project # if your change the path to any of them here, don't forget to make changes to 'cldeploy-precheck' log=/var/log/cldeploy.log lock=/var/lock/cldeploy.lck last_result_file=/var/run/cldeploy.last # contains exit code of last performed operation mode_file=/var/run/cldeploy.mode # contains last performed operation ("install"/"uninstall") precheck_log=/var/log/cldeploy-precheck.log # modprobe.d drop-in used on CL10 to defer kmod-lve autoload until after the # post-conversion reboot (see defer_kmodlve_autoload). Not shared with cldeploy-precheck. kmodlve_defer_conf=/etc/modprobe.d/cldeploy-defer-kmodlve.conf wget="/usr/bin/wget" wget_options="-q" kexec=false uninstall=false builddirectadmin=true regen_modprobe_conf=false activationkey="" components=false conversion=false hybridize=false no_force_hybridize=false cl_solo_edition=false cl_admin_edition=false cl_container=false solo_activation_key=false admin_activation_key=false hostinglimits=false conversiononly=false show_reboot_message=true hybridize_attempted=false skipkmodcheck=false skipbootcheck=false skipversioncheck=false skiposcheck=false skip_ea4_script_download=false base_repo_no_sslverify=false force_packages_installation=false unregistered_core_packages=false registration=true beta=false build_ids=() build_centos_ids=() base_repo_url="" addon_repo_urls=() addon_repo_names=() test_updates=false serverurl="https://xmlrpc.cln.cloudlinux.com/XMLRPC/" noninteractive=false cldeploy_started=false remove_non_standard_kernels=false precheck=false # adjust variables for container edition if [[ -f "${OPEN_VZ_MARKER}" || "${CLDEPLOY_TEST_MOCK_OPENVZ_MARKER}" == "true" ]]; then cl_container=true show_reboot_message=false fi # Update checker URL checksite="${PUBLIC_REPO_URL}/cloudlinux/sources/cln/" checkfile="version.dat" checkurl="$checksite$checkfile" scriptname="cldeploy" upgradeurl="$checksite$scriptname" script="cldeploy" dry_run="0" script="$1" case "$script" in ./*) script="`pwd`/`basename $script`" ;; /*) script="$script" ;; *) script="`pwd`/$script" ;; esac # special marks which are added to log during --precheck command, # they are used to parse the log in 'cldeploy-precheck' script in 'cpanel-lvemanager' project # if your change any of these marks, don't forget to make changes to 'cldeploy-precheck' CHECK_MARK="[CHECK]" FT_START_MARK="[FIX TIP START]" FT_END_MARK="[FIX TIP END]" MC_START_MARK="[MANDATORY CHANGE START]" MC_END_MARK="[MANDATORY CHANGE END]" } check_pipestatus() { if [ $PIPESTATUS -ne "$1" ]; then echo -e $2 | tee -a "${log}"; exit 1; fi; } # Check whether the exit code of last executed command matches the expected one, # and if not, write the error message and exit the script. # - error has occurred during precheck - write error to log # - error has occurred during conversion process - exit with error check_exit_code() { local exit_code=$? local expected_exit_code=$1 # "description" must have the following form: # "<msg if check is succeeded>|<msg if check is failed>" local description=$2 local fix_tip=$3 local message_for_cli=$4 if [ "$exit_code" -eq "$expected_exit_code" ]; then description="$(echo "$description" | awk -F '|' '{print $1}')" [ "$precheck" = "true" ] && echo "$CHECK_MARK $description - SUCCESS" | tee -a "${log}" return 0 fi description="$(echo "$description" | awk -F '|' '{print $2}')" # if precheck in progress, write special marks (intended to help log parsing) to the log [ "$precheck" = "true" ] && echo "$CHECK_MARK $description - FAILED" | tee -a "${log}" [ "$precheck" = "true" ] && echo "$FT_START_MARK" | tee -a "${log}" echo -e "$fix_tip" | tee -a "${log}" [ "$precheck" = "true" ] && echo "$FT_END_MARK" | tee -a "${log}" [ "$precheck" = "true" ] && return 1 [ -n "$message_for_cli" ] && echo -e "$message_for_cli" | tee -a "${log}" exit 1 } add_precheck_mandatory_change() { [ "$precheck" = "false" ] && return 0 echo "$MC_START_MARK" | tee -a "${log}" echo -e "$1" | tee -a "${log}" echo "$MC_END_MARK" | tee -a "${log}" } retry_wrapper() { for _ in {1..5}; do /bin/bash -c "set -o pipefail; $1" exit_code=$? if [[ ${exit_code} -ne 0 ]]; then continue else break fi done return "${exit_code}" } config_manager_wrapper() { local command_args command_args=$1 if [[ "$OS_VERSION" -ge "8" ]]; then retry_wrapper "dnf config-manager ${command_args}" else retry_wrapper "yum-config-manager ${command_args}" fi } # $1 = Message prompt # Returns ans=0 for no, ans=1 for yes yesno() { local message="$1" if [ "$precheck" = "true" ]; then add_precheck_mandatory_change "$message" ans=1 return 0 fi echo "$message" | tee -a "${log}" if [ $dry_run -eq 1 ] || [ "$noninteractive" = "true" ] then echo "Would be asked here if you wanted to continue (y/n - y is assumed)" ans=1 else ans=2 fi while [ $ans -eq 2 ] do echo -n "Do you want to continue (y/n)? " ; read reply case "$reply" in [yY][eE][sS]|[yY]) ans=1 ;; [nN][oO]|[nN]) ans=0 ;; *) echo "Please answer yes or no" ;; esac done } # $1 = Full URL to download # $2 = Optional basename to save to (if omitted, then = basename $1) download_file() { if [ "$2" = "" ] then dlbase="$(basename "$1")" else dlbase="$2" fi if [ $dry_run -eq 1 ] then echo "Would download this URL to $tmp_tree/$dlbase :" echo $1 ; echo return fi old_dlbase="$dlbase.old" if [ -f "$dlbase" ] then rm -f "$old_dlbase" mv -f "$dlbase" "$old_dlbase" fi echo "Downloading $dlbase ... Please wait" $wget $wget_options -O "$dlbase" "$1" if [ ! -s "$dlbase" ] then if [ -f "$old_dlbase" ] then mv -f "$old_dlbase" "$dlbase" fi echo "Failed to download $dlbase" exit 1 else echo "Succesfully downloaded $dlbase" fi } # Make sure that we are running the latest version # $*/$@ = Parameters passed to script check_script_version() { echo "Checking for an update to $scriptname" download_file "$checkurl" if [ $dry_run -eq 1 ] || [ "$noninteractive" = "true" ] then echo "Would check if this running script (version $version) is out of date." echo "If it's been superseded, the new version would be downloaded and you'd be asked" echo "if you want to upgrade to it and run the new version." echo return fi newversion="$(cat $checkfile)" rm -f "$checkfile" # The public version of the script is the same as the one we are running if [ "$newversion" = "$version" ]; then echo "$scriptname is already the latest version ($version) - continuing" # The public version of the script is older than the one we are running # sort -V | head -n1 picks the lower version number from the two elif [ "$(printf '%s\n' "$newversion" "$version" | sort -V | head -n1)" = "$newversion" ]; then echo "The version of $scriptname you are running is newer than the latest version ($newversion)" else echo "New version ($newversion) of $scriptname detected" echo "It will be downloaded and run now" yesno if [ $ans -eq 1 ]; then echo "OK, downloading and executing $script $*" download_file "$upgradeurl" if [ "$scriptname" -ef "$script" ]; then let a=1 else mv -f "$scriptname" "$script" fi chmod u+x "$script" echo "Download of $scriptname $newversion successful" rm -f $lock exec "$script" --skip-version-check "$@" error "Failed to run $script $*" else echo "A new version of the script is available: ${PUBLIC_REPO_URL}/cloudlinux/sources/cln/cldeploy" echo "Please download the new script, review code and run it." echo "If you would prefer to use the current version, run it with the \"--skip-version-check\" key." exit 1 fi fi } function check_solo_conversion_supported() { # This function call will check if conversion to CL SOLO is possible. # 1: Check if os version is other than 8 # Exit 0 in this cases. if [[ "${SKIP_PANEL_CHECK}" -eq 1 ]]; then echo "Skipping check_solo_conversion_supported" return 0 fi local description="CloudLinux OS Solo edition is compatible with your system|CloudLinux OS Solo edition is only compatible with AlmaLinux 8, 9 and 10" local fix_tip="You are trying to install CloudLinux OS Solo edition which is only compatible with AlmaLinux 8, 9 and 10. Please, use AlmaLinux 8, 9 or 10 server for conversion or install CloudLinux OS Solo using ISO. Also, take a look at this section of CloudLinux Solo documentation: https://docs.solo.cloudlinux.com/installation/ Please, contact CloudLinux support at https://cloudlinux.zendesk.com/ if you still have questions" [[ "$OS_VERSION" -ge "8" && "$OS_VERSION" -le "10" ]] check_exit_code 0 "$description" "$fix_tip" # Check that governor-mysql is not installed (it is not available on CL Solo) local conflicting_packages='governor-mysql' local description2="Your system doesn't contain packages that will be unavailable on CloudLinux OS Solo|Your system contains some packages that are not supported on CloudLinux OS Solo edition: ${conflicting_packages}" local fix_tip2="CloudLinux Solo provides less features than other editions, some packages installed on your system will stop working. Make sure to delete all packages from this list: ${conflicting_packages}. After that run cldeploy again More information about supported features can be found at https://www.cloudlinux.com/pricing/" rpm -q $conflicting_packages &>/dev/null check_exit_code 1 "$description2" "$fix_tip2" } function check_admin_conversion_supported() { # This function call will check if conversion to CL ADMIN is possible. # 1: Check if os version is other than 8 local description="CloudLinux OS Admin edition is compatible with your system|CloudLinux OS Admin edition is only compatible with AlmaLinux 8, 9 and 10" local fix_tip="You are trying to install CloudLinux OS Admin edition which is only compatible with AlmaLinux 8, 9 and 10. Please, use AlmaLinux 8, 9 or 10 server for conversion or install CloudLinux OS Admin using ISO. Also, take a look at this section of CloudLinux Admin documentation: https://docs.cloudlinux.com/cloudlinux_installation/ Please, contact CloudLinux support at https://cloudlinux.zendesk.com/ if you still have questions" [[ "$OS_VERSION" -ge "8" && "$OS_VERSION" -le "10" ]] check_exit_code 0 "$description" "$fix_tip" } check_kernel_update_permission() { if [ -e /etc/yum.conf ] && [ -n "$(grep exclude /etc/yum.conf | grep kernel | grep -v '^#')" ]; then yesno "Kernel update is prohibited on your system. Continuing the installation will upgrade the kernel." if [ $ans -eq 0 ]; then echo "Cannot run without upgrading kernel." | tee -a "${log}" rm -f $lock exit 1; fi fi local description="incompatible binary driver is not detected|binary driver is not compatible with CloudLinux kernel" local fix_tip="This server uses a binary driver hpahcisr.ko (HP AHCI Software RAID). That driver is not compatible with CloudLinux kernel. We don't know about any open source alternatives for that driver. The only workaround known to us at the moment is to disable the RAID feature in system BIOS and configure Linux software RAID instead. This workaround requires a full re-install of the OS." rpm -q --qf '%{name}\n' $(rpm -qa | grep hpahcisr) > /dev/null 2>&1 check_exit_code 1 "$description" "$fix_tip" if [ "$skipkmodcheck" = "false" ]; then list_not_compatible_kmods=$(rpm -q --qf '%{name}\n' $(rpm -qa | grep ^kmod-) | grep -v -e kvdo -e zfs -e lve -e iolimits -e aacraid -e megaraid_sas -e1000e -e r8168 -e microsoft -e igb -e ixgbe -e dell-dm-switch -e libs -e "^kmod$") local description="incompatible third-party kernel modules are not installed|incompatible third-party kernel modules are installed" local fix_tip="You have third-party kernel modules rpm installed: ${list_not_compatible_kmods} They are not compatible with CloudLinux kernel. Please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" [[ -z "${list_not_compatible_kmods}" ]] check_exit_code 0 "$description" "$fix_tip" fi local non_standard_kernels non_standard_kernels="$(uname -r | grep --invert-match $KERNEL_VERSION)" # Variable not empty if currently loaded kernel version does not start # with KERNEL_VERSION required for the major OS version detected if [ -n "$non_standard_kernels" ] ; then if uname -r | grep -q linode ; then if [ -f /proc/xen/capabilities ]; then LINODE=true else LINODE_KVM=true fi else yesno "Your server has non-standard kernel installed: ${non_standard_kernels}. Continuing the installation will unregister this kernel RPM from RPM database." if [ $ans -eq 0 ]; then echo "Please remove non-standard kernels manually and run this script again." | tee -a "${log}" rm -f $lock exit 1 fi remove_non_standard_kernels=true fi fi } function check_and_fix_almalinux_grub_symlink() { # CLOS-3167: special fix for hetzner images where symlink was malformed local TARGET_ABSOLUTE="/boot/efi/EFI/almalinux/grubenv" local TARGET_RELATIVE="../efi/EFI/almalinux/grubenv" local SYMLINK="/boot/grub2/grubenv" # Check if the file is a symlink if [ ! -L "$SYMLINK" ]; then return fi # Get the current target of the symlink local CURRENT_TARGET=$(readlink "$SYMLINK") # Check if it is an absolute symlink to the desired target if [ "$CURRENT_TARGET" == "$TARGET_ABSOLUTE" ]; then echo "[WORKAROUND]: $SYMLINK is an absolute symlink to $TARGET_ABSOLUTE." | tee -a "${log}" echo " Replacing it with relative link to fix boot issues." | tee -a "${log}" # Without pipefail, the return value of a pipeline is # the exit status of the last command in the pipeline, # regardless of whether previous commands failed. set -o pipefail # Create a relative symlink ln -sf "$TARGET_RELATIVE" "$SYMLINK" 2>&1 | tee -a "${log}" if [[ "$?" == "0" ]]; then echo "Successfully replaced $SYMLINK with a relative symlink to $TARGET_RELATIVE." | tee -a "${log}" else echo "Failed to replace $SYMLINK with a relative symlink to $TARGET_RELATIVE." | tee -a "${log}" fi set +o pipefail fi } check_yum () { # yum plugins enabled only when config contains local description="yum plugins are enabled|yum plugins are disabled" local fix_tip="Please enable yum-plugins: add string 'plugins=1' to the /etc/yum.conf" [ -n "$(cat /etc/yum.conf | sed -e 's/ //g' | grep -i ^"plugins=1")" ] check_exit_code 0 "$description" "$fix_tip" } check_dnf () { # dnf has another behavior: plugins are ENABLED unless config has plugins=False record local config="$(cat /etc/dnf/dnf.conf | sed -e 's/ //g')" local description="dnf plugins are enabled|dnf plugins are disabled" local fix_tip="Please enable dnf-plugins: remove string started with 'plugins=' from the /etc/dnf/dnf.conf" [[ -n "$(echo "${config}" | grep -i ^"plugins=False")" || -n "$(echo "${config}" | grep -i ^"plugins=0")" ]] check_exit_code 1 "$description" "$fix_tip" } check_system_supported() { local exit_code=0 local description="basic system checks passed|basic system checks failed" local message_for_cli="" if grep -iE "(ubuntu)|(debian)" /etc/os-release > /dev/null 2>&1; then exit_code=1 local fix_tip="Conversion from Ubuntu is not supported." local message_for_cli="Please, use the ubuntu2cloudlinux.py script to convert to CloudLinux OS." elif ! rpm -q --whatprovides redhat-release > /dev/null 2>&1; then exit_code=1 local fix_tip="There is no package providing /etc/redhat-release, please install redhat-release or centos-release or almalinux-release" elif [ "$OS_VERSION" != 5 ] && [ "$OS_VERSION" != 6 ] && [ "$OS_VERSION" != 7 ] && [ "$OS_VERSION" != 8 ] && [ "$OS_VERSION" != 9 ] && [ "$OS_VERSION" != 10 ]; then exit_code=1 local fix_tip="Conversion is available for Version 6, 7, 8, 9 and 10 only." elif [[ "$skiposcheck" == "false" && "$OS_VERSION" -ge 7 ]]; then check_cl_release_available if [[ $? -ne 0 && "$INSTALL_LOWER_VERSION" != "true" ]]; then exit_code=1 local distro distro="$(detect_distro)" local fix_tip="WARNING: Your ${distro} release version is greater then the latest currently available CloudLinux release!\nYou can either wait for a new version of CloudLinux or downgrade your ${distro} installation version to ${LAST_CL_VERSION}.${LAST_CL_RELEASE}\nDowngrade conversion is currently supported only for installations without panel or with one of the following panels: cPanel, Plesk." local message_for_cli="To continue the conversion anyway, you may also run cldeploy with --skip-os-check option,\nbut there are no guarantees that it won't cause any issues after the conversion." fi fi # Currently no OS+panel combinations are unsupported, but we keep this check here for future use - e.g. CL10 # if [[ "$skiposcheck" == "false" && "$OS_VERSION" -ge "10" && "$PANEL" =~ ^(directadmin)$ ]]; then # exit_code=1 # local fix_tip="The installed control panel \"${PANEL}\" is not officially supported in combination with the CloudLinux OS version ${OS_VERSION}." # local message_for_cli="To continue the conversion anyway, you may run cldeploy with --skip-os-check option,\nbut do so at your own risk. There are no guarantees that the system will be stable or functional after the conversion." # fi [ $exit_code -eq 0 ] # if this check failed, we exit immediately even during precheck as system is not supported ! check_exit_code 0 "$description" "$fix_tip" "$message_for_cli" && exit 1 } function set_base_url_lower_version { CLOUDLINUX_RELEASE_PACKAGES_DIR_URL="${CURRENT_REPO_URL}/cloudlinux/${LOWER_VERSION_RELEASE}/BaseOS/x86_64/os/Packages/" CLOUDLINUX_RELEASE_PACKAGE=$(curl -L "${CLOUDLINUX_RELEASE_PACKAGES_DIR_URL}" 2>/dev/null | sed -n "s/^.*\(cloudlinux-release.*rpm\).*$/\1/p" | tail -1) CLOUDLINUX_RELEASE="${CLOUDLINUX_RELEASE_PACKAGES_DIR_URL}${CLOUDLINUX_RELEASE_PACKAGE}" } check_release () { ARCH=$(uname -i) # Fallback to uname -m if uname -i returns "unknown" if [[ "$ARCH" == "unknown" ]]; then ARCH=$(uname -m) fi CPU=$(uname -p) # handle 32bit xen with x86_64 host kernel # Use glibc's RPM %{ARCH} metadata instead of querying by arch suffix, # because x86_64_v2/v3/v4 microarchitecture levels use different suffixes # (e.g. glibc.x86_64_v2) that don't match the literal ".x86_64" query. if [[ "$ARCH" = "x86_64" ]] && ! rpm -q glibc --queryformat '%{ARCH}\n' 2>/dev/null | grep -q '^x86_64'; then ARCH=i386 CPU=i686 fi if [[ "$OS_VERSION" -eq "7" ]]; then KERNEL_VERSION="3.10.0" if [[ -n "$CLOUDLINUX_RELEASE_URL" ]]; then CLOUDLINUX_RELEASE="$CLOUDLINUX_RELEASE_URL" else CLOUDLINUX_RELEASE="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/cloudlinux/7/${ARCH}/cloudlinux7-release-current.${CPU}.rpm" fi if [[ -n "$CLOUDLINUX_EA4_RELEASE_URL" ]]; then CLOUDLINUX_EA4_RELEASE="$CLOUDLINUX_EA4_RELEASE_URL" else CLOUDLINUX_EA4_RELEASE="${CURRENT_REPO_URL}/cloudlinux/EA4/cloudlinux-ea4-release-latest-7.noarch.rpm" fi CLOUDLINUX_LOGOS="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/cloudlinux/7/${ARCH}/cloudlinux-logos-70.0.3-5.el7.noarch.rpm" CENTOS_RELEASE="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/centos/7/${ARCH}/centos7-release-current.${CPU}.rpm" elif [[ "$OS_VERSION" -eq "8" ]]; then KERNEL_VERSION="4.18.0" if [[ "$CLDEPLOY_TEST_SET_LOWER_VERSION_AS_CURRENT" == "true" ]]; then set_base_url_lower_version echo "Note: Using cloudlinux-release package from fixed URL ${CLOUDLINUX_RELEASE}" | tee -a "${log}" elif [[ -n "$CLOUDLINUX_RELEASE_URL" ]]; then CLOUDLINUX_RELEASE="$CLOUDLINUX_RELEASE_URL" else CLOUDLINUX_RELEASE="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/cloudlinux/${OS_VERSION}/x86_64/cloudlinux${OS_VERSION}-release-current.x86_64.rpm" fi if [[ -n "$CLOUDLINUX_EA4_RELEASE_URL" ]]; then CLOUDLINUX_EA4_RELEASE="$CLOUDLINUX_EA4_RELEASE_URL" else CLOUDLINUX_EA4_RELEASE="${CURRENT_REPO_URL}/cloudlinux/EA4/cloudlinux-ea4-release-latest-8.noarch.rpm" fi CLOUDLINUX_LOGOS="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/cloudlinux/8/x86_64/cloudlinux8-logos-current.x86_64.rpm" CENTOS_RELEASE="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/centos/8/x86_64/centos8-release-current.x86_64.rpm" CENTOS_GPG_KEYS="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/centos/8/x86_64/centos-gpg-keys-current.x86_64.rpm" CENTOS_REPOS="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/centos/8/x86_64/centos-repos-latest.x86_64.rpm" ALMALINUX_RELEASE="${ALMALINUX_REPO_URL}/almalinux/almalinux-release-latest-8.x86_64.rpm" elif [[ "$OS_VERSION" -eq "9" ]]; then KERNEL_VERSION="5.14.0" if [[ "$CLDEPLOY_TEST_SET_LOWER_VERSION_AS_CURRENT" == "true" ]]; then set_base_url_lower_version echo "Note: Using cloudlinux-release package from fixed URL ${CLOUDLINUX_RELEASE}" | tee -a "${log}" elif [[ -n "$CLOUDLINUX_RELEASE_URL" ]]; then CLOUDLINUX_RELEASE="$CLOUDLINUX_RELEASE_URL" else CLOUDLINUX_RELEASE="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/cloudlinux/9/x86_64/cloudlinux9-release-current.x86_64.rpm" fi if [[ -n "$CLOUDLINUX_EA4_RELEASE_URL" ]]; then CLOUDLINUX_EA4_RELEASE="$CLOUDLINUX_EA4_RELEASE_URL" else CLOUDLINUX_EA4_RELEASE="${CURRENT_REPO_URL}/cloudlinux/EA4/cloudlinux-ea4-release-latest-9.noarch.rpm" fi CLOUDLINUX_LOGOS="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/cloudlinux/9/x86_64/cloudlinux9-logos-current.x86_64.rpm" CENTOS_RELEASE="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/centos/9/x86_64/centos9-release-current.noarch.rpm" CENTOS_GPG_KEYS="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/centos/9/x86_64/centos-gpg-keys-current.noarch.rpm" CENTOS_REPOS="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/centos/9/x86_64/centos-repos-current.noarch.rpm" ALMALINUX_RELEASE="${ALMALINUX_REPO_URL}/almalinux/almalinux-release-latest-9.x86_64.rpm" elif [[ "$OS_VERSION" -eq "10" ]]; then KERNEL_VERSION="6.12.0" if [[ "$CLDEPLOY_TEST_SET_LOWER_VERSION_AS_CURRENT" == "true" ]]; then echo "WARNING: lower-version testing mode is not supported for CL 10. Please unset CLDEPLOY_TEST_SET_LOWER_VERSION_AS_CURRENT." | tee -a "${log}" exit 1 elif [[ -n "$CLOUDLINUX_RELEASE_URL" ]]; then CLOUDLINUX_RELEASE="$CLOUDLINUX_RELEASE_URL" else CLOUDLINUX_RELEASE="${CURRENT_REPO_URL}/cloudlinux/10/cloudlinux-release-latest-10.rpm" fi if [[ -n "$CLOUDLINUX_EA4_RELEASE_URL" ]]; then CLOUDLINUX_EA4_RELEASE="$CLOUDLINUX_EA4_RELEASE_URL" else CLOUDLINUX_EA4_RELEASE="${CURRENT_REPO_URL}/cloudlinux/EA4/cloudlinux-ea4-release-latest-10.noarch.rpm" fi # CL10 identifies as AlmaLinux, so no logos package needed # CLOUDLINUX_LOGOS="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/cloudlinux/10/x86_64/cloudlinux10-logos-current.x86_64.rpm" CENTOS_RELEASE="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/centos/10/x86_64/centos10-release-current.noarch.rpm" CENTOS_GPG_KEYS="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/centos/10/x86_64/centos-gpg-keys-current.noarch.rpm" CENTOS_REPOS="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/centos/10/x86_64/centos-repos-current.noarch.rpm" ALMALINUX_RELEASE="${ALMALINUX_REPO_URL}/almalinux/almalinux-release-latest-10.x86_64.rpm" fi } check_digitalocean () { if [ -f /etc/digitalocean ]; then yesno "This looks like DigitalOcean droplet. DigitalOcean doesn't allow custom kernel installations via grub. Continuing the installation requires the kexec mechanism for CloudLinux kernel to be enabled." if [ $ans -eq 0 ]; then echo "Exiting" | tee -a "${log}" rm -f $lock exit 1 fi kexec=true echo "Enabled" | tee -a "${log}" fi } # The usage of this function is currently commented out. # shellcheck disable=SC2317 check_linode_kvm () { if uname -r | grep -q linode && [ ! -f /proc/xen/capabilities ] ; then yesno "This looks like Linode KVM. Linode KVM doesn't let custom kernel installations via grub. Continuing installation requires enabled kexec mechanism for CloudLinux kernel." if [ $ans -eq 0 ]; then echo "Exiting" | tee -a "${log}" rm -f "$lock" exit 1 fi kexec=true echo "Enabled" | tee -a "${log}" fi } backup_file() { local file_name="$1" if [[ -f "$file_name" ]]; then \mv -f "$file_name" "${BACKUP}" fi } erase_package_via_yum() { local package_name="$1" if rpm -q "$package_name" > /dev/null 2>&1; then yum erase -y "$package_name" fi } erase_package_via_rpm() { local package_name="$1" if rpm -q "$package_name" > /dev/null 2>&1; then rpm --erase --nodeps "$package_name" fi } save_repo_status() { local repo="$1" if ! yum repolist all | grep -q "^$repo "; then echo "Repository '$repo' does not exist." return 1 fi local status status="$(config_manager_wrapper --dump "$repo" | grep --only-matching 'enabled = [0-1]' | cut -d' ' -f3)" echo "$status" > "$BACKUP/$repo.status" } restore_repo_status() { local repo="$1" local status_file="$BACKUP/$repo.status" if [ ! -f "$status_file" ]; then echo "No saved status found for repository '$repo'." return 1 fi local status="$(cat $status_file)" if [ "$status" -eq "1" ]; then config_manager_wrapper --enable "$repo" else config_manager_wrapper --disable "$repo" fi } function handle_els_packages() { local TMP_DIR="${BACKUP}/tmp" local failed_pkgs=() # Create backup and temp directories mkdir -p "${BACKUP}" "${TMP_DIR}" || { echo "Failed to create backup/temp directories" | tee -a "${log}" return 1 } # Only proceed for CentOS 7 [[ "$OS_VERSION" != "7" ]] && { rm -rf "${TMP_DIR}" return 0 } # Check if ELS repositories are present if ! ls /etc/yum.repos.d/centos*els*.repo &> /dev/null; then echo "No ELS repositories found. Skipping ELS package handling..." | tee -a "${log}" rm -rf "${TMP_DIR}" return 0 fi echo "ELS repositories detected. Processing ELS packages before conversion..." | tee -a "${log}" # Create package backup list rpm -qa | sort > "${BACKUP}/els_packages_backup_$(date +%Y%m%d_%H%M%S).txt" || { echo "Failed to create package backup list" | tee -a "${log}" return 1 } # Prevent ELS packages from being reinstalled if ! grep -q "exclude=\*.tuxcare.els\*" /etc/yum.conf; then { echo echo "# Added by cldeploy" echo "exclude=*.tuxcare.els*" } >> /etc/yum.conf || { echo "Failed to update yum.conf" | tee -a "${log}" return 1 } fi # Save and disable ELS repos cp /etc/yum.repos.d/centos*els*.repo "${BACKUP}/" || { echo "Failed to backup ELS repo files" | tee -a "${log}" return 1 } echo "Disabling ELS repositories..." | tee -a "${log}" yum-config-manager --disable centos7-els || { echo "Failed to disable centos7-els repo" | tee -a "${log}" return 1 } yum-config-manager --disable centos7els-rollout-* || { echo "Failed to disable centos7els-rollout repos" | tee -a "${log}" return 1 } # Remove els-define package if present if rpm -q els-define &> /dev/null; then yum remove -y els-define || { echo "Failed to remove els-define package" | tee -a "${log}" return 1 } fi # Get list of installed ELS packages echo "Checking for ELS packages..." | tee -a "${log}" local els_pkgs=$(rpm -qa | grep -E '\.tuxcare\.els[0-9]') if [ -n "$els_pkgs" ]; then echo "Found ELS packages:" | tee -a "${log}" echo "$els_pkgs" | tee -a "${log}" # Create a yum shell script local TMPFILE TMPFILE=$(mktemp "${TMP_DIR}/yum_commands.XXXXXX") || { echo "Failed to create temporary file" | tee -a "${log}" return 1 } echo "# yum shell commands" > "$TMPFILE" # Process each package while read -r pkg; do # Get base package name local base_name base_name=$(rpm -q --queryformat "%{NAME}" "$pkg") || continue if [ -n "$base_name" ]; then # Add shell commands to replace package { echo "remove $pkg" echo "install $base_name" } >> "$TMPFILE" fi done <<< "$els_pkgs" # Add transaction commands { echo "run" echo "exit" } >> "$TMPFILE" # Execute the yum shell script echo "Replacing ELS packages with base versions..." | tee -a "${log}" if ! yum shell -y "$TMPFILE" 2>&1 | tee -a "${log}"; then echo "Yum shell failed, trying alternative approach..." | tee -a "${log}" while read -r pkg; do base_name=$(rpm -q --queryformat "%{NAME}" "$pkg") || continue if [ -n "$base_name" ]; then if ! yum downgrade -y "$base_name" 2>&1 | tee -a "${log}"; then failed_pkgs+=("$pkg") fi fi done <<< "$els_pkgs" fi rm -f "$TMPFILE" fi # Move ELS repo files to backup if ! mv -f /etc/yum.repos.d/centos*els*.repo "${BACKUP}/" 2>&1 | tee -a "${log}"; then echo "Warning: Failed to move ELS repo files to backup" | tee -a "${log}" fi # Handle TuxCare GPG key if [ -f "/etc/pki/rpm-gpg/RPM-GPG-KEY-TuxCare" ]; then if ! mv -f "/etc/pki/rpm-gpg/RPM-GPG-KEY-TuxCare" "${BACKUP}/" 2>&1 | tee -a "${log}"; then echo "Warning: Failed to move TuxCare GPG key to backup" | tee -a "${log}" fi fi # Clean up yum clean all 2>&1 | tee -a "${log}" || true rm -rf "${TMP_DIR}" # Report any failures if [ ${#failed_pkgs[@]} -gt 0 ]; then echo "Failed to downgrade the following packages:" | tee -a "${log}" printf '%s\n' "${failed_pkgs[@]}" | tee -a "${log}" return 1 fi echo "ELS package handling complete" | tee -a "${log}" return 0 } backup () { mkdir -p "${BACKUP}" | tee -a "${log}" if [ "$OS_VERSION" -ge "9" ]; then save_repo_status crb &>> "${log}" fi yes | cp /etc/redhat-release "${BACKUP}" 2>&1 | tee -a "${log}" # disable redhat backup_file "/etc/yum.repos.d/RedHat-Base.repo" &>> "${log}" erase_package_via_yum rhnlib &>> "${log}" # Old rhn-client-tools builds (stock EL ones, e.g. from the satellite-5-client # module on EL8, or leftovers of a previous attempt) conflict with current # cloudlinux-release. Erase it so the release package installs cleanly; # registration installs the current one later. erase_package_via_yum rhn-client-tools &>> "${log}" erase_package_via_yum subscription-manager &>> "${log}" erase_package_via_rpm redhat-release-notes &>> "${log}" erase_package_via_rpm redhat-release &>> "${log}" erase_package_via_rpm redhat-logos &>> "${log}" erase_package_via_rpm redhat-release-server &>> "${log}" backup_file "/etc/sysconfig/rhn/systemid" &>> "${log}" backup_file "/etc/yum/pluginconf.d/rhnplugin.conf" &>> "${log}" # disable centos backup_file "/etc/yum.repos.d/CentOS-AppStream.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-Base.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-CR.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-Debuginfo.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-Extras.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-Media.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-PowerTools.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-Sources.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-Vault.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-centosplus.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-fasttrack.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-Stream-AppStream.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-Stream-Base.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-Stream-Debuginfo.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-Stream-Extras.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-Stream-Media.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-Stream-PowerTools.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-Stream-Sources.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-Stream-Vault.repo" &>> "${log}" backup_file "/etc/yum.repos.d/CentOS-Stream-centosplus.repo" &>> "${log}" erase_package_via_rpm centos-release &>> "${log}" erase_package_via_rpm centos-release-notes &>> "${log}" erase_package_via_rpm redhat-logos &>> "${log}" erase_package_via_rpm centos-logos &>> "${log}" # disable scientific linux backup_file "/etc/yum.repos.d/sl.repo" &>> "${log}" backup_file "/etc/yum.repos.d/cd.repo" &>> "${log}" erase_package_via_rpm sl-release &>> "${log}" erase_package_via_rpm sl-release-notes &>> "${log}" # disable almalinux* repos # don't move repos to backup here, because cloudlinux-release # contains same files as almalinux-release # mv breaks retries of cldeploy if ls /etc/yum.repos.d/almalinux*.repo > /dev/null 2>&1; then yes | cp /etc/yum.repos.d/almalinux*.repo "${BACKUP}" &>> "${log}" fi # CL10+ subsystem: keep AlmaLinux identity packages if [[ "$OS_VERSION" -ge "10" ]]; then echo "CloudLinux ${OS_VERSION}: Keeping almalinux-release/repo/logo in subsystem mode" | tee -a "${log}" else erase_package_via_rpm almalinux-release &>> "${log}" erase_package_via_rpm almalinux-repos &>> "${log}" erase_package_via_rpm almalinux-logos &>> "${log}" fi # disable rocky* repos if ls /etc/yum.repos.d/Rocky*.repo > /dev/null 2>&1; then yes | mv /etc/yum.repos.d/Rocky*.repo "${BACKUP}" &>> "${log}" fi erase_package_via_rpm rocky-release &>> "${log}" erase_package_via_rpm rocky-logos &>> "${log}" erase_package_via_rpm rocky-repos &>> "${log}" } function is_cpanel_ea4() { if [[ "cpanel" == "${PANEL}" && -f "/etc/cpanel/ea4/is_ea4" ]]; then return 0 else return 1 fi } function yum_exclude_packages() { EXCLUDED_PACKAGES+=" $1" } function apply_yum_excludes() { # No point in doing anything if there's no excluded packages. if [[ -z "${EXCLUDED_PACKAGES}" ]]; then return fi # EXCLUDED_PACKAGES has a space at the beginning. :1 removes it. EXCLUDED_PACKAGES="${EXCLUDED_PACKAGES:1}" local grep_result # Either add a new line to the config, or append packages to an existing one. for config_file in '/etc/yum.conf' '/etc/dnf/dnf.conf' ; do if [[ -f $config_file ]]; then grep_result=$(grep "^exclude=" $config_file) if [[ -n $grep_result ]]; then sed -i "s/\(^exclude=.*$\)/\1 ${EXCLUDED_PACKAGES}/" $config_file else echo "exclude=${EXCLUDED_PACKAGES}" >> $config_file fi # Insert the message before the "exclude" line. sed -i "/exclude=.*$/ i\ # The exclude pattern list was extended by the CloudLinux deployment script.\n\ # They will be automatically removed once a new CloudLinux release becomes available.\n\ # CloudLinux automatic exclude list: $EXCLUDED_PACKAGES" $config_file fi done } prep () { # localinstall is used because it can correctly handle direct url installations on old yum as well if [[ "$OS_VERSION" -ge "7" ]]; then # Install alt-common-release to set up the ALT auxiliary repositories. ALT_COMMON_RELEASE="https://repo.alt.tuxcare.com/alt-common/alt-common-release-install.x86_64.rpm" retry_wrapper "yum localinstall -y ${ALT_COMMON_RELEASE} --disablerepo='*' &>> ${log}" check_pipestatus 0 "Unable to install alt-common-release, please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-TuxCare fi retry_wrapper "yum localinstall -y ${CLOUDLINUX_RELEASE} --disablerepo='*' &>> ${log}" check_pipestatus 0 "Unable to install cloudlinux-release, please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CloudLinux # Install logos package only if CLOUDLINUX_LOGOS is defined and not empty if [[ -n "${CLOUDLINUX_LOGOS}" ]]; then retry_wrapper "yum localinstall -y ${CLOUDLINUX_LOGOS} --disablerepo='*' |& grep -v \"${ROLLOUT_WARNING_FILTER}\" &>> ${log}" else echo "Note: CLOUDLINUX_LOGOS is not set, skipping logos installation" | tee -a "${log}" fi # The CRB repository from almalinux-release is removed in backup() # Its replacement coming from cloudlinux-release is disabled by default # On cPanel this repo being disabled can lead to package resolution errors # after conversion, so we restore its state # See https://cloudlinux.atlassian.net/browse/CLOS-2174 if [ "$OS_VERSION" -ge "9" ]; then restore_repo_status crb &>> "${log}" fi if [[ "$OS_VERSION" -ge "8" ]]; then ALMALINUX_BASE="baseos" # Special handling for versions >= CL10 - use new repository structure (no BaseOS) if [[ "$OS_VERSION" -eq "10" ]]; then URL_BASE_REPO="${CURRENT_REPO_URL}/cloudlinux/${OS_VERSION}/cloudlinux-x86_64-server-${OS_VERSION}/x86_64/os/" else URL_BASE_REPO="${CURRENT_REPO_URL}/cloudlinux/${OS_VERSION}/BaseOS/x86_64/os/" fi else BASE_REPO="cloudlinux-base" fi if [[ "$INSTALL_LOWER_VERSION" == "true" ]]; then # Guard: lower-version is not supported for CL10+ if [[ "${OS_VERSION}" -ge "10" ]]; then echo "WARNING: lower-version downgrade is not supported for CL10+. Please use CL10 repositories without minor downgrade." | tee -a "${log}" exit 1 fi # replace lower CL release version with current Almalinux release version in almalinux repos for repo_conf in /etc/yum.repos.d/almalinux-*.repo; do [[ -f "$repo_conf" ]] && sed -i "s/$LOWER_VERSION_RELEASE/$OS_VERSION.$OS_RELEASE/" "$repo_conf" done # cl-mysql packages have a bumped epoch, which is why a normal yum upgrade # can actually decrement the MySQL version # we don't want that, because MySQL doesn't support working with databases from higher versions # and will refuse to run if downgraded yum_exclude_packages "mysql* mariadb*" echo "Note: Setting $OS_VERSION.$OS_RELEASE to /etc/dnf/vars/almalinux_releasever" | tee -a "${log}" echo "$OS_VERSION.$OS_RELEASE" > /etc/dnf/vars/almalinux_releasever echo "Note: Setting ${LOWER_VERSION_RELEASE} to /etc/dnf/vars/cloudlinux_releasever" | tee -a "${log}" echo "${LOWER_VERSION_RELEASE}" > /etc/dnf/vars/cloudlinux_releasever URL_BASE_REPO="${CURRENT_REPO_URL}/cloudlinux/${LOWER_VERSION_RELEASE}/BaseOS/x86_64/os/" fi # set base repo from cldeploy argument if provided if [[ -n "${base_repo_url}" ]]; then URL_BASE_REPO="${base_repo_url}" fi if is_cpanel_ea4; then retry_wrapper "yum localinstall -y ${CLOUDLINUX_EA4_RELEASE} --disablerepo='*' |& grep -v \"${ROLLOUT_WARNING_FILTER}\" &>> ${log}" fi # Handle LES if [[ -x "/usr/local/sbin/les" ]]; then LES=true /usr/local/sbin/les -da 2>&1 | tee -a "${log}" check_pipestatus 0 "Unable to turn off LES, please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" fi # install packages providing config-manager if [[ "$OS_VERSION" -ge "8" ]]; then dnf install -y --disablerepo=cloudlinux-rollout-* 'dnf-command(config-manager)' | tee -a "${log}" else yum install -y --disablerepo=cloudlinux-rollout-* yum-utils |&\ grep -v \"${ROLLOUT_WARNING_FILTER}\" | tee -a "${log}" fi # add external repos for repo_url in "${addon_repo_urls[@]}"; do config_manager_wrapper "--add-repo=${repo_url} |& grep -v \"${ROLLOUT_WARNING_FILTER}\"" done # set up base repo if [[ -n "${URL_BASE_REPO}" ]]; then if [[ "$OS_VERSION" -ge "10" ]]; then # CL10+: Don't add BASE_REPO via config-manager, cloudlinux-release already provides it # Force x86_64 architecture (cloudlinux-release may create "unknown" repo name) BASE_REPO="cloudlinux-x86_64-server-$OS_VERSION" echo "CL${OS_VERSION}: Using repository '${BASE_REPO}' provided by cloudlinux-release package" | tee -a "${log}" else echo "Configuring Base repo: ${URL_BASE_REPO}" | tee -a "${log}" config_manager_wrapper "--add-repo=${URL_BASE_REPO} |& grep -v \"${ROLLOUT_WARNING_FILTER}\"" BASE_REPO="$(echo ${URL_BASE_REPO##*://} | tr / _)" fi if [[ "$base_repo_no_sslverify" == "true" ]]; then echo "Disabling sslverify for the configured base repo: ${URL_BASE_REPO}" | tee -a "${log}" config_manager_wrapper "--save --setopt ${BASE_REPO}.sslverify=0" fi fi echo "Note: Base repo name: ${BASE_REPO}" | tee -a "${log}" } check_panel () { PANEL="" ROOT_PLESK_DIR="/usr/local/psa/admin/" ROOT_CPANEL_DIR="/usr/local/cpanel/whostmgr/docroot/" ROOT_IWORX_DIR="/usr/local/interworx/" ROOT_ISPMGR_DIR="/usr/local/ispmgr/" ROOT_ISPMGR5_FILE="/usr/local/mgr5/sbin/mgrctl" ROOT_DA_DIR="/usr/local/directadmin/" CUSTOM_PANEL_INTEGRATION_FILE="/opt/cpvendor/etc/integration.ini" if [ -d $ROOT_PLESK_DIR ]; then PANEL="plesk"; fi if [ -d $ROOT_IWORX_DIR ]; then PANEL="interworx"; fi if [ -d $ROOT_CPANEL_DIR ]; then PANEL="cpanel"; fi if [ -d $ROOT_ISPMGR_DIR ]; then PANEL="ispmgr"; fi if [ -d $ROOT_DA_DIR ]; then PANEL="directadmin"; fi if [ -f $CUSTOM_PANEL_INTEGRATION_FILE ]; then PANEL="CUSTOM-PANEL"; fi if [ -f $ROOT_ISPMGR5_FILE ]; then PANEL="ispmgr5"; fi if [ "$PANEL" != "" ] && [ "$PANEL" = "cpanel" ] && [ -x /usr/local/cpanel/cpanel ] ; then CPANEL_MAJOR=$(/usr/local/cpanel/cpanel -V | cut -f 1 -d ".") CPANEL_MINOR=$(/usr/local/cpanel/cpanel -V | cut -f 2 -d ".") if [ $CPANEL_MAJOR -eq 11 ] && [ $CPANEL_MINOR -lt 30 ]; then CPANEL_OLD=YES else CPANEL_OLD=NO fi fi if [ "$PANEL" != "" ] && [ "$PANEL" = "plesk" ] && [ -f /usr/local/psa/version ] ; then PLESK_MAJOR=$(cut -f 1 -d "." /usr/local/psa/version) PLESK_MINOR=$(cut -f 2 -d "." /usr/local/psa/version) if [ $PLESK_MAJOR -eq 11 ] && [ $PLESK_MINOR -lt 5 ]; then PLESK_OLD=YES else PLESK_OLD=NO fi fi } function check_panel_features() { local resctrl_bin="/usr/local/psa/admin/bin/resctrl" if [[ -f "${resctrl_bin}" ]]; then local resctrl_status="$(${resctrl_bin} --status)" if [[ "${resctrl_status}" == "enabled" ]]; then echo "Plesk Cgroups Manager resource controller extension is incompatible with CloudLinux." | tee -a "${log}" echo "Extension must be deleted before upgrading the system." | tee -a "${log}" yesno "Would you like to remove Plesk Cgroups Manager automatically?" if [ $ans -eq 1 ]; then echo "Removing incompatible component." | tee -a "${log}" "${resctrl_bin}" --disable && /sbin/plesk installer remove --components resctrl | tee -a "${log}" else echo "Automatic plugin uninstallation aborted" | tee -a "${log}" echo "You can use the following command to run the uninstallation manually" | tee -a "${log}" echo " ${resctrl_bin} --disable && /sbin/plesk installer remove --components resctrl" | tee -a "${log}" exit 1 fi fi fi } function check_that_groups_clsupergid_and_clsudoers_are_empty () { local var_lve="/var/lve" local already_passed="${var_lve}/.clsupergid_clsudoers_check_is_passed.cldeploy" local check=0 if [[ -f "${already_passed}" ]]; then echo "Check that groups clsupergid and clsudoers are empty is skipped, because it has already been performed" >> "${log}" return 0 fi # check that the special groups don't contain any user local result echo "Check that groups clsupergid and clsudoers are empty" >> "${log}" result=$(getent group clsupergid | awk -F ':' '{print $4; exit}' 2>&1) echo "Check that the group clsupergid doesn't contain any user" >> "${log}" echo "${result}" >> "${log}" [[ "" != "${result}" ]] && (( check++ )) result=$(getent group clsudoers | awk -F ':' '{print $4; exit}' 2>&1) echo "Check that the group clsudoers doesn't contain any user" >> "${log}" echo "${result}" >> "${log}" [[ "" != "${result}" ]] && (( check++ )) # check that no account has one of the special groups as its primary GID # (primary membership lives in /etc/passwd, not in getent group field 4) local grp gid for grp in clsupergid clsudoers; do gid=$(getent group "${grp}" | cut -d ':' -f 3) echo "Check that no user has the group ${grp} as their primary GID" >> "${log}" if [[ "" != "${gid}" ]]; then result=$(getent passwd | awk -F ':' -v gid="${gid}" '$4 == gid {print $1}') echo "${result}" >> "${log}" [[ "" != "${result}" ]] && (( check++ )) fi done # check that the users with special names don't belong to special groups echo "Check that the user clsupergid doesn't belong to the group with same name" >> "${log}" id -ng "clsupergid" 2>/dev/null | grep -w "clsupergid" >> "${log}" && (( check++ )) echo "Check that the user clsupergid doesn't belong to the group with same name" >> "${log}" id -ng "clsudoers" 2>/dev/null | grep -w "clsudoers" >> "${log}" && (( check++ )) local description="groups clsupergid and clsudoers are empty|groups clsupergid and clsudoers are not empty" local fix_tip="You have users in the group 'clsudoers', 'clsupergid' or both. This may create a security issue on the server, because after the conversion the users in those groups will be granted permissions higher than of a simple user. Please move the users to another group(s)." [[ "0" == "${check}" ]] ! check_exit_code 0 "$description" "$fix_tip" && return 1 mkdir -p "${var_lve}" chmod 755 "${var_lve}" touch "${already_passed}" } check_cloudlinux_repos () { ENABLED_REPOS="--disablerepo=* --enablerepo=cloudlinux-$ARCH-server-$OS_VERSION" if [[ "0" != "${#addon_repo_urls[@]}" ]]; then ENABLED_REPOS="${ENABLED_REPOS} --enablerepo=$(echo "${addon_repo_names[@]}")" fi if [[ -n "${build_ids[*]}" ]]; then for build_id in "${build_ids[@]}"; do ENABLED_REPOS="${ENABLED_REPOS} --enablerepo=${build_id}" done fi if [[ -n "${build_centos_ids[*]}" ]]; then for build_id in "${build_centos_ids[@]}"; do ENABLED_REPOS="${ENABLED_REPOS} --enablerepo=${build_id}" done fi ENABLED_REPOS="${ENABLED_REPOS} --enablerepo=${BASE_REPO}" if [[ "${OS_VERSION}" -ge "8" ]]; then ENABLED_REPOS="${ENABLED_REPOS} --enablerepo=baseos --enablerepo=appstream" fi if [[ "${OS_VERSION}" -ge "7" ]]; then ENABLED_REPOS="${ENABLED_REPOS} --enablerepo=alt-common" fi if [[ "true" == "${test_updates}" ]]; then ENABLED_REPOS="${ENABLED_REPOS} --enablerepo=cloudlinux-updates-testing" fi # CLDEPLOY-133. We should enable cl-ea4 repo for updating package `mod_lsapi` to CL package, # because lve-utils conflicts with cpanel package `mod_lsapi` if is_cpanel_ea4 && [[ "true" == "${test_updates}" ]]; then ENABLED_REPOS="${ENABLED_REPOS} --enablerepo=cl-ea4,cl-ea4-testing" elif is_cpanel_ea4; then ENABLED_REPOS="${ENABLED_REPOS} --enablerepo=cl-ea4" fi } create_repos () { if [[ -n "${build_ids[*]}" ]] || [[ -n "${build_centos_ids[*]}" ]]; then local bs_deployment_tool_url="https://build.cloudlinux.com/api/v1/deployment-tool/" local deploy_dst_file="/var/run/deploy.py" download_file "${bs_deployment_tool_url}" "${deploy_dst_file}" | tee -a "${log}" for i in "${!build_ids[@]}"; do retry_wrapper "${PYTHON_BIN} ${deploy_dst_file} --with-linked -t ${auth_token} ${build_ids[i]} 2>&1 | tee -a ${log}" if [ $? -ne 0 ]; then unset 'build_ids[i]' fi done for i in "${!build_centos_ids[@]}"; do retry_wrapper "${PYTHON_BIN} ${deploy_dst_file} --with-linked -t ${auth_token} ${build_centos_ids[i]} 2>&1 | tee -a ${log}" if [ $? -ne 0 ]; then unset 'build_centos_ids[i]' fi done fi } # We need to install kernel-devel for virtual containers check_source () { [ "$precheck" = "true" ] && return 0 NEED_SOURCE="NO" #check if pci bus is exist in system. in openvz pci bus is absent if [ -e /proc/bus/pci ] ; then if ! rpm -q pciutils > /dev/null 2>&1; then retry_wrapper "yum -y install pciutils" fi if [ -x /sbin/lspci ] ; then if $(/sbin/lspci -n | grep -q 1414) || $(/sbin/lspci -n | grep -q 15ad) || $(/sbin/lspci -n | grep -q 1ab8); then NEED_SOURCE="YES" fi fi fi } fix_mdadm_config() { python -c ' import sys import subprocess import os import shutil MDADM = "/sbin/mdadm" MDADM_CONF = "/etc/mdadm.conf" out_put = subprocess.Popen([MDADM, "--detail", "--scan"], stdout = subprocess.PIPE) mdadm = out_put.stdout.readlines() result_output = """MAILADDR root AUTO +imsm +1.x -all """ for line in mdadm: for item in line.split(): if "/dev" in item: dev = item elif "UUID" in item: uuid = item out = subprocess.Popen([MDADM,"--detail", dev], stdout = subprocess.PIPE) mdadm_scan_out = out.stdout.readlines() for line in mdadm_scan_out: if "Raid Level" in line: raid_level = line.split(":")[1].strip() elif "Raid Devices" in line: raid_devices = line.split(":")[1].strip() result_string = "ARRAY " + dev.strip() + " level=" + raid_level + " num-devices=" + raid_devices + " " + uuid +"\n" result_output = result_output + result_string if os.path.exists(MDADM_CONF): shutil.copyfile(MDADM_CONF, MDADM_CONF + "." + str(os.getpid())) conf = open(MDADM_CONF, "w") conf.write(result_output) conf.close() ' } add_raid_to_grub(){ python -c ' import os import subprocess import shutil GRUB_CFG_DEFAULT = "/etc/default/grub" OPTIONS = ["net.ifnames=0", "rd.auto=1"] grub_data = open(GRUB_CFG_DEFAULT).readlines() grub_data_result = "" add_opt = "" try: for line in grub_data: if "GRUB_CMDLINE_LINUX" in line: for opt in OPTIONS: if opt not in line: add_opt = add_opt + opt + " " line_new = line[:-2] + " " + add_opt.strip() + "\"\n" grub_data_result = grub_data_result + line_new else: grub_data_result = grub_data_result + line if os.path.exists(GRUB_CFG_DEFAULT): shutil.copyfile(GRUB_CFG_DEFAULT, GRUB_CFG_DEFAULT + "." + str(os.getpid())) except (OSError, IOError): grub_data_result = "GRUB_CMDLINE_LINUX=\"net.ifnames=0 rd.auto=1\"" conf = open(GRUB_CFG_DEFAULT, "w") conf.write(grub_data_result) conf.close() # In general, there is no 100% reliable way to find where is current # grub config because its location is embedded to binary EFI stub during # grub-install and, in general case, could be anywhere on disk, # BUT usually its location follows such pattern "/boot/efi/EFI/XYZ/grub.cfg" # where XYZ is a efi entry name which is for CentOS 7 == "centos" and # "redhat" for earlie versions. # Also, by default there are few symlinks that may point to correct file: # /etc/grub2.cfg -> ../boot/grub2/grub.cfg # /etc/grub2-efi.cfg -> ../boot/efi/EFI/centos/grub.cfg GRUB_CFG_PATH_1 = "/boot/grub2/grub.cfg" GRUB_CFG_PATH_2 = "/etc/grub2-efi.cfg" found_any_grub_cfg = False if os.path.exists(GRUB_CFG_PATH_1): found_any_grub_cfg = True # write file anyway for additional safety: subprocess.call(["/usr/sbin/grub2-mkconfig", "-o", GRUB_CFG_PATH_1]) if os.path.exists("/sys/firmware/efi"): # will be False if symlink points to not existed file if os.path.exists(GRUB_CFG_PATH_2): found_any_grub_cfg = True subprocess.call(["/usr/sbin/grub2-mkconfig", "-o", GRUB_CFG_PATH_2]) else: print("*" * 10) print("WARNING: Your EFI-based system doesnt have correct symlink " "\"/etc/grub2-efi.cfg\" this may cause boot troubles. " "Please, fix it to point to your current grub.cfg file and run " "grub2-mkconfig -o /etc/grub2-efi.cfg") print("*" * 10) if not found_any_grub_cfg: print("*" * 10) print("WARNING: Unable to find grub.cfg in a few default locations. " "It will be generated to {}".format(GRUB_CFG_PATH_1)) print("Its STRONGLY recommended to check your GRUB configuration and " "ensure that GRUB is configured to use exactly this file BEFORE " "reboot, because else it may refuse to boot!") print("*" * 10) ' } add_dracut_config(){ # This is a Python script, we don't want to expand anything. # shellcheck disable=SC2016 python -c ' import os import shutil import glob, re, rpm import subprocess DRACUT_CFG = "/etc/dracut.conf.d/raid.conf" dracut_cfg_result = "" try: for line in open(DRACUT_CFG): if line.startswith("add_drivers"): if "$add_drivers" not in line: result_line = "add_drivers=\"$add_drivers raid1 raid0\"" dracut_cfg_result = dracut_cfg_result + result_line else: dracut_cfg_result = dracut_cfg_result + line if "$add_drivers" not in dracut_cfg_result: dracut_cfg_result = dracut_cfg_result + "add_drivers=\"$add_drivers raid1 raid0\"\n" if os.path.exists(DRACUT_CFG): shutil.copyfile(DRACUT_CFG, DRACUT_CFG + "." + str(os.getpid())) except (OSError, IOError): dracut_cfg_result = "add_drivers=\"$add_drivers raid1 raid0\"\n" conf = open(DRACUT_CFG, "w") conf.write(dracut_cfg_result) conf.close() list = sorted([(h["version"], h["release"], h["arch"]) for h in rpm.TransactionSet().dbMatch(rpm.RPMTAG_NAME, "kernel")], cmp=lambda b, a: rpm.labelCompare(("0", a[0], a[1]), ("0", b[0], b[1]))) for kernel in list: if "lve" in kernel[1]: version = kernel[0] release = kernel[1] arch = kernel[2] break lve_kernel_version = version + "-" + release + "." + arch subprocess.call(["/usr/bin/dracut", "-f", "/boot/initramfs-" + lve_kernel_version + ".img", lve_kernel_version]) ' } # This function is currently unused, commented out and replaced with fix_mdadm_config # shellcheck disable=SC2317 mdadm_conf_error(){ echo -e "\e[1m\e[31m" echo "Invalid /etc/mdadm.conf file detected, please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" | tee -a "${log}" echo -e "\e[0m" rm -f "$lock" exit 1 } check_mdadm_conf() { # CLDEPLOY-43 - Detect wrong formatted /etc/mdadm.conf file if [ -f /etc/mdadm.conf ]; then if grep -i -e '^ARR' /etc/mdadm.conf &>/dev/null; then if ! grep -i -e '^AUT' /etc/mdadm.conf &>/dev/null; then #mdadm_conf_error fix_mdadm_config fi options_count=0 first_array=1 for p in $(grep -i -e '^ARR' /etc/mdadm.conf); do if echo "$p" | grep -i -e '^ARR' &>/dev/null; then if [ $first_array -ne 1 ]; then if [ $options_count -lt 1 ]; then #mdadm_conf_error fix_mdadm_config fi options_count=0 else first_array=0 fi else if echo "$p" | grep '=' &>/dev/null; then options_count=$(expr $options_count + 1) fi fi done if [ $options_count -lt 1 ]; then #mdadm_conf_error fix_mdadm_config fi fi fi } # Tricks for OVH hosting check_ovh () { if [ -f /etc/sysconfig/mkinitrd/OVH ] && [ -h /sys/block/sda/device ] && [ "$OS_VERSION" -eq "5" ] ; then devicepath=$(readlink /sys/block/sda/device) if [ -f /sys/block/sda/$devicepath/../../../uevent ]; then . /sys/block/sda/$devicepath/../../../uevent if [ -n "$DRIVER" ] && ! grep "${DRIVER}" /etc/modprobe.conf | grep -q scsi_hostadapter ; then cat /etc/modprobe.conf | grep -v scsi_hostadapter > /root/modprobe.conf.$$ echo "alias scsi_hostadapter $DRIVER" >> /root/modprobe.conf.$$ mv /etc/modprobe.conf /etc/modprobe.conf.orig mv /root/modprobe.conf.$$ /etc/modprobe.conf cat /root/modprobe.conf.$$ fi fi rm -f /etc/sysconfig/mkinitrd/OVH if [ -L /etc/mtab ] ; then rm /etc/mtab cp /proc/mounts /etc/mtab fi fi # OVH CentOS7 if [ -f /etc/grub.d/06_OVHkernel ] ; then add_raid_to_grub add_dracut_config fi # check mdadm.conf if [ -f /etc/sysconfig/mkinitrd/OVH ] || [ -f /etc/grub.d/06_OVHkernel ]; then check_mdadm_conf fi } # Root device link check_root_device_link () { if [ ! -e /dev/root ]; then if grep -q ^/ /etc/fstab; then ln -s $(awk '{ if ($2 == "/") print $1; }' /etc/fstab) /dev/root fi fi } add_efi_cl_boot_record() { if [[ ! -d /sys/firmware/efi ]]; then return fi local device local disk_name local disk_num local soft_dev1 local soft_dev2 local disk_name1 local disk_name2 local disk_num1 local disk_num2 device="$(df -T /boot/efi | sed -n 2p | awk '{print $1}')" if [[ $device == *"/dev/md"* ]]; then echo "ESP Partition on software raid detected:" | tee -a "${log}" soft_dev1=/dev/"$(cat /proc/mdstat | grep "${device:5} " | awk '{print $5}' | head -c -4)" soft_dev2=/dev/"$(cat /proc/mdstat | grep "${device:5} " | awk '{print $6}' | head -c -4)" echo "$soft_dev1" | tee -a "${log}" echo "$soft_dev2" | tee -a "${log}" disk_name1="$(echo "${soft_dev1}" | sed -re 's/(p|)[0-9]$//g')" disk_name2="$(echo "${soft_dev2}" | sed -re 's/(p|)[0-9]$//g')" disk_num1="$(echo "${soft_dev1}" | tail -c 2 | sed 's/[^0-9]//g')" disk_num2="$(echo "${soft_dev2}" | tail -c 2 | sed 's/[^0-9]//g')" else disk_name="$(echo "${device}" | sed -re 's/(p|)[0-9]$//g')" disk_num="$(echo "${device}" | tail -c 2 | sed 's/[^0-9]//g')" fi if [[ $device == *"/dev/md"* ]]; then efibootmgr -c -L "CloudLinux" -l "\EFI\centos\shimx64.efi" -d "${disk_name1}" -p "${disk_num1}" | tee -a "${log}" efibootmgr -c -L "CloudLinux" -l "\EFI\centos\shimx64.efi" -d "${disk_name2}" -p "${disk_num2}" | tee -a "${log}" else efibootmgr -c -L "CloudLinux" -l "\EFI\centos\shimx64.efi" -d "${disk_name}" -p "${disk_num}" | tee -a "${log}" fi } function enable_use_pam() { sed -i 's/^#UsePAM no/UsePAM yes/' /etc/ssh/sshd_config } check_update_uefi_boot_entries() { if [[ ! -d /sys/firmware/efi ]]; then return fi # Starting from CL9 we use AlmaLinux kernel and don't have to modify UEFI boot entries # return early if we are on CL9 or CL10 if [[ "$OS_VERSION" -ge "9" ]]; then return fi # duplicating this logic here to fix # A dirty hack to make UEFI boot record re-creation code below actually triggered during tests. # For more info, have a look at CLOS-2252. if [[ $CLDEPLOY_TEST_ABSENT_CL_UEFI_RECORD == "true" ]]; then efibootmgr | grep CloudLinux | awk '{print substr($1,5,4)}' | xargs -I {} efibootmgr -B -b {} fi local bios_vendor bios_vendor="$(dmidecode -s bios-vendor)" if [[ "$bios_vendor" == *Dell* ]]; then echo "Your UEFI vendor is detected as Dell. In some cases this firmware can't automatically update UEFI Boot Entries, so we have to delete old AlmaLinux entries in cldeploy" | tee -a "${log}" echo -e "Current state of 'efibootmgr -v' is\n$(efibootmgr -v)" >>$log local almalinux_entries almalinux_entries="$(efibootmgr -v | grep AlmaLinux | sed 's/Boot\(.\{4\}\).*/\1/')" echo -e "The following bootnums will be deleted:\n$almalinux_entries" | tee -a "${log}" for i in $almalinux_entries; do efibootmgr -B -b "$i" done echo "EFI boot record for AlmaLinux is deleted" | tee -a "${log}" fi # Sometimes, grub-mkconfig doesn't properly create UEFI boot entries for CloudLinux in previous steps, # so we've added a fallback mechanism here. # Also, don't add new records if cldeploy is executed second time on the same server. if ! efibootmgr | grep CloudLinux >/dev/null; then add_efi_cl_boot_record fi # check that efibootmgr output contains CloudLinux record that points to existing file # example of full record: Boot0003* CloudLinux HD(2,MBR,0x28056f88,0x200800,0x12c000)/File(\EFI\centos\shimx64.efi) # example of cl_loader value: /EFI/centos/shimx64.efi # there are 2 CloudLinux records in case of RAID1 cl_loader="$(efibootmgr -v | grep --max-count=1 CloudLinux | sed 's/^.*File(\([^)]*\))/\1/' | tr '\\' '/')" check_pipestatus 0 "cldeploy failed to add CloudLinux UEFI Boot Entry. Please don't reboot the server and contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" cl_loader_path="/boot/efi${cl_loader}" if [[ ! -f $cl_loader_path ]]; then echo "WARNING: CloudLinux UEFI Boot Entry points to non-existing file $cl_loader_path" | tee -a "${log}" echo "Please don't reboot the server and contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" | tee -a "${log}" exit 1 else echo "The new EFI boot record for CloudLinux is added" | tee -a "${log}" fi } print_help () { cat << EOF >&2 Usage: -h, --help Print this message -k, --key <key> Convert your system to CloudLinux with an activation key (may instead be supplied via the CLDEPLOY_ACTIVATION_KEY environment variable to keep it off the command line) -i, --byip Convert your system to CloudLinux and register by IP -c, --uninstall Convert CloudLinux back to CentOS -y, --noninteractive Assume user answered yes to all the questions --serverurl Use a non-default registration server (default is https://xmlrpc.cln.cloudlinux.com/XMLRPC) --components-only Install control panel components only --conversion-only Do not install control panel components after converting --hostinglimits Install mod_hostinglimits rpm --skip-kmod-check Skip the check for unsupported kmods --skip-boot-check Skip checking that etc/fstab configuration is explicit about device mounting on boot/efi --skip-version-check Do not check for cldeploy script updates --skip-os-check Do not check whether conversion to CloudLinux is supported for the running OS release --skip-registration Don't register on CLN if CL repositories are already accessible --force-hybridize After end of converting it allows to hybridize machine from CloudLinux 7 to CloudLinux 7 Hybrid, which has a newer kernel then CL7 --no-force-hybridize Don't hybridize machine from CloudLinux 7 to CloudLinux 7 Hybrid automatically, even though machine has a new hardware --to-solo-edition Convert to CloudLinux Solo edition (only allowed with --skip-registration option) --to-admin-edition Convert to CloudLinux Admin edition (only allowed with --skip-registration option) --to-container-environment Convert to CloudLinux with support for working inside containers --force-packages-installation Automatically resolve dependencies and remove conflicting packages --unregistered-core-packages Install core packages even with --skip-registration. CL10 only. --testing-repos Enable cloudlinux-updates-testing and cl-ea4-testing repositories --base-repo-url <url> URL of a base repository which will be used instead of the predefined CloudLinux one --base-repo-no-sslverify Disable SSL verification (sslverify=0) for the base repository --addon-repo-urls <url,url> URLs of additional repositories which will be used in addition to existing (e.g. migration or specific kernel repos). Values should be separated by a comma. --precheck Check if the system is ready to be converted to CloudLinux --skip-ea4-script-download Do not download the cloudlinux_ea3_to_ea4 script from a remote repository during conversion on cPanel EOF } # For internal use only: # # -a, --alt-repo <build_id> Add a build from alternatives to repolist (each build_id needs another flag) # --centos-repo <build_id> Add a CentOS build from alternatives to repolist (each build_id needs another flag) # -t, --auth-token <token> Personal Build System authentication token # (may instead be supplied via the CLDEPLOY_AUTH_TOKEN # environment variable to keep it off the command line) write_linode_grub_conf () { if [ -e /boot/grub/grub.conf ]; then cp /boot/grub/grub.conf /boot/grub/grub.conf.backup fi mkdir -p /boot/grub/ if [ "$OS_VERSION" -eq "6" ]; then KVERSION=$(python -c 'import glob, re, rpm; print "%s-%s.%s" % sorted([(h["version"], h["release"], h["arch"]) for h in rpm.TransactionSet().dbMatch(rpm.RPMTAG_NAME, "kernel")], cmp=lambda b, a: rpm.labelCompare(("0", a[0], a[1]), ("0", b[0], b[1])))[0]') cat > /boot/grub/grub.conf << EOF default=0 timeout=5 hiddenmenu title CloudLinux ($KVERSION) root (hd0) kernel /boot/vmlinuz-$KVERSION ro root=/dev/xvda xencons=tty console=tty1 console=hvc0 crashkernel=auto SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us initrd /boot/initramfs-$KVERSION.img EOF fi if [ "$OS_VERSION" -eq "5" ]; then KVERSION=$(rpm -q kernel-xen --qf "%{version}-%{release}\n" | sort | tail -1)xen cat > /boot/grub/grub.conf << EOF default=0 timeout=5 title CentOS ($KVERSION) root (hd0) kernel /boot/vmlinuz-$KVERSION root=/dev/xvda console=xvc0 xencons=xvc0 initrd /boot/initrd-$KVERSION.img EOF fi ln -sf /boot/grub/grub.conf /boot/grub/menu.lst ln -sf /boot/grub/grub.conf /etc/grub.conf } add_digitalocean_kexec () { if [ $kexec == true ]; then retry_wrapper "yum -y install kexec-tools 2>&1 | tee -a ${log}" cat > /etc/rc.d/init.d/kexec << EOF #!/bin/bash # # Boot CloudLinux kernel via kexec # # chkconfig: 345 01 99 . /etc/init.d/functions if [ "\$1" != "start" ]; then exit 0 fi touch /var/lock/subsys/local latestkernel=\`python -c 'import glob, re, rpm; print "%s-%s.%s" % sorted(filter(lambda r: r is not None, [re.search("/boot/vmlinuz-([^-]+)-(.*?)\.([^\.]+)$", f) for f in glob.glob("/boot/vmlinuz-*lve*")]), cmp=lambda b, a: rpm.labelCompare(("0", a.group(1), a.group(2)), ("0", b.group(1), b.group(2))))[0].groups()'\` if [ ! -f /boot/try-boot-cl-kernel ]; then touch /boot/try-boot-cl-kernel kexec -l /boot/vmlinuz-\${latestkernel} --initrd=/boot/initramfs-\${latestkernel}.img --append="$(cat /proc/cmdline)" kexec -e else rm /boot/try-boot-cl-kernel fi EOF /bin/chmod a+x /etc/rc.d/init.d/kexec /sbin/chkconfig --add kexec 2>&1 | tee -a "${log}" fi } check_and_fix_grub_efi_cfg() { if [ -e /sys/firmware/efi ]; then # current cfg for grub in centos and cloudlinux grub 2 on efi systems # 2018.10.31. Centos 7 OVH image provides broken grub2-efi-x64 package with strange custom grub binary. # This custom grub2 build uses config from /boot/grub2/grub.conf # After update to new version of grub2-efi-x64 (centos\cloudlinux) grub2 binary is changed. # Original grub2 efi build uses config from /boot/efi/EFI/centos/grub.cfg # So we need to create this config before installation CL and kernel. # By default in almalinux boot folder is /boot/efi/EFI/almalinux/*. # Package grub2-efi creates centos folder and associated files in /boot/efi/EFI/centos/* # OUR package from CLOUDLINUX repos uses "centos" directory # After package installation, file grub.cfg does not exist in /boot/efi/EFI/centos folder, also /etc/grub2-efi.cfg link is broken # Attention: Broken link doesn't cause boot issue. # We have to regenerate grub.cfg file in /boot/efi/EFI/centos/ after converting to CloudLinux and also to solve boot problems. CL_GRUB_EFI_DIR="/boot/efi/EFI/centos" CL_GRUB_EFI_CFG="${CL_GRUB_EFI_DIR}/grub.cfg" if [[ -d "$CL_GRUB_EFI_DIR" && ! -e "$CL_GRUB_EFI_CFG" ]]; then echo "WARNING: grub config $CL_GRUB_EFI_CFG for EFI system not found." | tee -a "${log}" grub2-mkconfig -o "$CL_GRUB_EFI_CFG" 2>&1 | tee -a "${log}" # this should fix grub2 packages retry_wrapper "yum -y reinstall grub2* 2>&1 | tee -a ${log}" fi fi } remove_unified_cgroup_hierarchy_from_grub() { # Remove 'systemd.unified_cgroup_hierarchy=1' option from /etc/default/grub. # This option prevents loading kmod-lve modules. GRUB_SETTINGS_FILE="/etc/default/grub" OPTION="systemd.unified_cgroup_hierarchy=1" if [ -e "$GRUB_SETTINGS_FILE" ] && grep -q "$OPTION" "$GRUB_SETTINGS_FILE"; then sed -i "s/\s*$OPTION//g" "$GRUB_SETTINGS_FILE" echo "Removed $OPTION option from $GRUB_SETTINGS_FILE." | tee -a "${log}" # need to rebuild grub.cfg after removing grub2-mkconfig -o /boot/grub2/grub.cfg 2>&1 | tee -a "${log}" if [[ -e /sys/firmware/efi && -d /boot/efi/EFI/centos ]]; then grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg 2>&1 | tee -a "${log}" fi fi } defer_kmodlve_autoload() { # CL10 only. The stock AlmaLinux 10 kernel boots with Intel CET/IBT # (Indirect Branch Tracking) enabled. kmod-lve is not IBT-instrumented, so # loading it while IBT is active triggers a fatal control-protection (#CP) # fault and panics the server. The CloudLinux tuned profile disables IBT via # the bootloader cmdline (ibt=off), but that only takes effect after a reboot. # # During conversion the lve package chain loads the module on the still-IBT- # active kernel: lve-utils %posttrans restarts the lvectl/lve_namespaces # services, which Want lve.service, which runs 'modprobe kmodlve'. Block every # modprobe of kmodlve for the duration of the conversion; lve.service loads the # module normally on the next boot, by which point ibt=off is in effect. # # Scoped to editions that actually load kmod-lve: Solo and Container do not # load the module, so they never hit this panic and need no deferral. [[ "$OS_VERSION" -ge "10" ]] || return 0 [[ "${cl_solo_edition}" == "true" || "${cl_container}" == "true" ]] && return 0 cat > "$kmodlve_defer_conf" <<'EOF' # Added by cldeploy: defer kmod-lve autoload until after the post-conversion reboot. # On CL10 the stock kernel boots with Intel CET/IBT enabled and kmod-lve is not # IBT-instrumented, so loading it before the CloudLinux tuned profile applies # 'ibt=off' (which requires a reboot) panics the kernel. This turns any # 'modprobe kmodlve' into a no-op; cldeploy removes this file once the CloudLinux # tuned profile is active, and lve.service then loads the module on the next boot. install kmodlve /bin/true EOF echo "Deferred kmod-lve module load until after reboot (CL10 Intel IBT safety)" | tee -a "${log}" } restore_kmodlve_autoload() { # Counterpart to defer_kmodlve_autoload. Only re-enable autoload once the # CloudLinux tuned profile is active, i.e. 'ibt=off' is queued for the next # boot - otherwise removing the block would just move the panic to first boot. [[ -e "$kmodlve_defer_conf" ]] || return 0 if grep -q cloudlinux /etc/tuned/active_profile 2>/dev/null; then # plain rm (no -f): the guard above guarantees the file exists, and the # CI custom-checker forbids "rm -f <variable>". rm "$kmodlve_defer_conf" echo "Re-enabled kmod-lve autoload; module will load on next boot with ibt=off active" | tee -a "${log}" else echo "WARNING: CloudLinux tuned profile is not active; kmod-lve autoload is left disabled" | tee -a "${log}" echo "to prevent a kernel panic on the next boot (Intel CET/IBT). Ensure the CloudLinux" | tee -a "${log}" echo "tuned profile is applied and the system is rebooted with ibt=off, then remove" | tee -a "${log}" echo "${kmodlve_defer_conf} to enable LVE." | tee -a "${log}" fi } generate_sysinfo_cpanel() { if [ -e /scripts/gensysinfo ]; then rm -f /var/cpanel/sysinfo.config /scripts/gensysinfo fi } kernel_debug_output() { echo echo "=== DEBUG OUTPUT ===" [[ -e /sys/firmware/efi ]] && echo -e "Looks like system is EFI-based\n" [[ ${skipkmodcheck} == "true" ]] && echo -e "WARN: --skip-kmod-check option was used. It's dangerous because it may hide critical compatibility problems.\n" echo "uname -r :"; uname -r echo echo "ls -la /boot : "; ls -la /boot echo echo "ls -l /etc/grub2.cfg :"; ls -l /etc/grub2.cfg echo "=== //DEBUG OUTPUT ===" } print_error_about_wrong_kernel() { local path_to_initramfs="${1}" local path_to_kernel="${2}" echo "WARNING! Please check validity of default grub record" | tee -a ${log} echo "Parameters \"initrd\" and \"linux\" should point to those that are installed by CloudLinux, but found:" | tee -a ${log} echo "\"initrd\"=${path_to_initramfs}" | tee -a ${log} echo "\"linux\"=${path_to_kernel}" | tee -a ${log} echo "PLEASE DO NOT REBOOT SERVER. See article https://cloudlinux.zendesk.com/hc/en-us/articles/360017630613" | tee -a ${log} kernel_debug_output | tee -a ${log} show_reboot_message=false } check_validity_of_default_grub_record() { # We install grubby if one is absent if [[ ! -e "$(which grubby)" ]]; then retry_wrapper "yum -y install grubby 2>&1 | tee -a ${log}" fi local kernel local initrd local path_to_initramfs kernel="$(grubby --info=DEFAULT | grep "^kernel=" | awk -F= '$1=="kernel" {print $2; exit}')" # remove '"' symbol from the start (##) and from the end (%%) of parameter # (used on cl8, but on cl6/7 parameter is without '"') kernel="${kernel%%\"}" local path_to_kernel="${kernel##\"}" initrd="$(grubby --info=DEFAULT | grep "^initrd=" | awk -F= '$1=="initrd" {print $2; exit}')" # remove '"' symbol from the start (##) and from the end (%%) of parameter initrd="${initrd%%\"}" path_to_initramfs="$(echo ${initrd##\"} | awk -F ' ' '{print $1; exit}')" if [[ ! -e "${path_to_kernel}" || ! -e "${path_to_initramfs}" ]]; then echo "WARNING!!! Please check existence of files ${path_to_kernel} and ${path_to_initramfs}" | tee -a ${log} echo "PLEASE DO NOT REBOOT SERVER IF THOSE ARE NOT EXISTS. See article https://cloudlinux.zendesk.com/hc/en-us/articles/360017630613" | tee -a ${log} kernel_debug_output | tee -a ${log} # /boot/vmlinuz-3.10.0-962.3.2.lve1.5.24.3.el7.x86_64 # /boot/initramfs-3.10.0-962.3.2.lve1.5.24.3.el7.x86_64.img # It works without pipefail options else if [[ "${OS_VERSION}" -ge "8" ]]; then local title=$(grubby --info=DEFAULT | grep "^title=" | awk -F= '$1=="title" {print $2; exit}') if [[ -z $(grep -i "el${OS_VERSION}" <<< "${path_to_initramfs}") ]] || [[ -z $(grep -i "el${OS_VERSION}" <<< "${path_to_kernel}") ]] || [[ -z $(grep -i "CloudLinux" <<< "${title}") && "$OS_VERSION" -le "8" ]] || [[ -z $(grep -iE "(AlmaLinux|CloudLinux)" <<< "${title}") && "$OS_VERSION" -ge "9" && "$INSTALL_LOWER_VERSION" == "false" ]] || [[ -z $(grep -i "CloudLinux" <<< "${title}") && "$OS_VERSION" -ge "9" && "$INSTALL_LOWER_VERSION" == "true" ]]; then print_error_about_wrong_kernel "${path_to_initramfs}" "${path_to_kernel}" fi else if ! echo "${path_to_initramfs}" | grep -i lve | grep -i "el${OS_VERSION}" &> /dev/null || ! echo "${path_to_kernel}" | grep -i lve | grep -i "el${OS_VERSION}" &> /dev/null; then print_error_about_wrong_kernel "${path_to_initramfs}" "${path_to_kernel}" # Defense-in-depth: if hybridization was attempted, the default kernel must carry # the hybrid dist tag (`el7h`). Without this, an `el7` substring trivially matches # the pre-hybrid kernel and the check above can't distinguish hybridized from not. elif [[ "${hybridize_attempted}" == "true" ]] && \ ( ! grep -iq "el${OS_VERSION}h" <<< "${path_to_initramfs}" || ! grep -iq "el${OS_VERSION}h" <<< "${path_to_kernel}" ); then echo "WARNING! Hybridization was attempted but the default GRUB entry is not a hybrid kernel." | tee -a "${log}" print_error_about_wrong_kernel "${path_to_initramfs}" "${path_to_kernel}" fi fi fi } function check_and_fix_grub_settings() { # Check a set of statements for EFI and non-EFI systems # ensuring that they are true or fix them if needed # Currently, the fix only applies to GRUB settings for CL8 systems # Also skipped for containers as they don't have a CL-specific kernel if [[ "${cl_container}" == "true" || "${OS_VERSION}" -ne "8" ]]; then return fi # Check that /etc/default/grub contains GRUB_ENABLE_BLSCFG=true and GRUB_DEFAULT=saved add_parameter_to_default_grub_cfg "GRUB_ENABLE_BLSCFG" "true" && BLSCFG_CHANGED=true add_parameter_to_default_grub_cfg "GRUB_DEFAULT" "saved" if [[ -e /sys/firmware/efi ]]; then check_and_fix_grub_settings_efi else check_and_fix_grub_settings_non_efi fi regenerate_grub_conf /usr/bin/systemctl restart tuned | tee -a "${log}" } function add_parameter_to_default_grub_cfg() { local parameter="${1}" local value="${2}" local default_grub_cfg="/etc/default/grub" if ! grep -q "${parameter}" "${default_grub_cfg}"; then echo "WARNING: ${default_grub_cfg} does not contain the ${parameter} parameter" | tee -a "${log}" echo -e "\n# added by CloudLinux" >> "${default_grub_cfg}" echo "${parameter}=${value}" >> "${default_grub_cfg}" echo "${parameter}=${value}" was added to "${default_grub_cfg}" | tee -a "${log}" return 0 elif [[ ! "$(grep "${parameter}" ${default_grub_cfg} | awk -F= '{print $2}')" =~ \"?${value}\"? ]] \ || [[ $(grep -c -P "^\s*#\s*${parameter}" "${default_grub_cfg}") != "0" ]]; then echo "$(grep "${parameter}" ${default_grub_cfg}) was found" | tee -a "${log}" sed -i -r "s/(#\s*)?${parameter}="?.*"?/${parameter}=${value}/g" "${default_grub_cfg}" echo "The ${parameter} value was changed to ${value} in ${default_grub_cfg}" | tee -a "${log}" return 0 fi return 1 } function check_and_fix_grub_settings_efi() { # The 'grub2-efi-x64' package must be installed with the '.cloudlinux' suffix in its name # This ensures the package is installed or updated to the latest version retry_wrapper "yum -y ${ENABLED_REPOS} --disableexcludes=all install grub2-efi-x64 2>&1 | tee -a ${log}" # Should not occur since we have installed/updated the package, but just in case if ! rpm -q grub2-efi-x64 > /dev/null; then echo "WARNING: grub2-efi-x64 package is not installed" | tee -a "${log}" elif ! rpm -q grub2-efi-x64 | grep -q \.cloudlinux; then echo "WARNING: grub2-efi-x64 package does not contain cloudlinux suffix in its name" | tee -a "${log}" fi local grub_etc_cfg="/etc/grub2-efi.cfg" local grub_efi_cfg="/boot/efi/EFI/centos/grub.cfg" local grub_efi_cfg_rel_link="../boot/efi/EFI/centos/grub.cfg" local grubenv_cfg="/boot/grub2/grubenv" local grubenv_efi_cfg="/boot/efi/EFI/centos/grubenv" local grubenv_efi_cfg_rel_link="../efi/EFI/centos/grubenv" # '/etc/grub2-efi.cfg' must be a symlink to the '../boot/efi/EFI/centos/grub.cfg': # /etc/grub2-efi.cfg -> ../boot/efi/EFI/centos/grub.cfg check_and_fix_grub_cfg_symlink "${grub_etc_cfg}" "${grub_efi_cfg_rel_link}" # '/boot/efi/EFI/centos/grub.cfg' must exist and be a regular file (not symlink) check_and_fix_grub_cfg "${grub_efi_cfg}" # '/boot/efi/EFI/centos/grubenv' must exist and be a regular file (not symlink) check_and_fix_grubenv_cfg "${grubenv_efi_cfg}" # '/boot/grub2/grubenv' must be a symlink to the '../efi/EFI/centos/grubenv': # /boot/grub2/grubenv -> ../efi/EFI/centos/grubenv if [[ ! -e "${grubenv_cfg}" ]]; then echo "WARNING: ${grubenv_cfg} does not exist, it should be a symlink pointing to ${grubenv_efi_cfg_rel_link}" | tee -a "${log}" recreate_symlink "${grubenv_cfg}" "${grubenv_efi_cfg_rel_link}" elif [[ -f "${grubenv_cfg}" && ! -L "${grubenv_cfg}" ]]; then echo "WARNING: invalid ${grubenv_cfg}, it should be a symlink pointing to ${grubenv_efi_cfg_rel_link}" | tee -a "${log}" # If the file is not a symlink, then we need to copy it to a proper place, that is /boot/efi/EFI/centos/grubenv recreate_symlink "${grubenv_cfg}" "${grubenv_efi_cfg_rel_link}" "${grubenv_efi_cfg}" elif [[ -L "${grubenv_cfg}" && "$(readlink ${grubenv_cfg})" != "${grubenv_efi_cfg_rel_link}" ]]; then echo "WARNING: invalid ${grubenv_cfg}, it should be a symlink pointing to ${grubenv_efi_cfg_rel_link}" | tee -a "${log}" recreate_symlink "${grubenv_cfg}" "${grubenv_efi_cfg_rel_link}" fi } function check_and_fix_grub_settings_non_efi() { # The 'grub2-efi-x64' package is NOT installed retry_wrapper "yum -y remove grub2-efi-x64 2>&1 | tee -a ${log}" # Should not occur since we have removed the package, but just in case if rpm -q grub2-efi-x64 > /dev/null; then echo "WARNING: grub2-efi-x64 package is installed" | tee -a "${log}" fi local grub_etc_cfg="/etc/grub2.cfg" local grub_cfg="/boot/grub2/grub.cfg" local grub_cfg_rel_link="../boot/grub2/grub.cfg" local grubenv_cfg="/boot/grub2/grubenv" # '/etc/grub2.cfg' is a symlink to the '../boot/grub2/grub.cfg': # /etc/grub2.cfg -> ../boot/grub2/grub.cfg check_and_fix_grub_cfg_symlink "${grub_etc_cfg}" "${grub_cfg_rel_link}" # '/boot/grub2/grub.cfg' must exist and be a regular file (not symlink) check_and_fix_grub_cfg "${grub_cfg}" # '/boot/grub2/grubenv' exists and is a regular file (not symlink) check_and_fix_grubenv_cfg "${grubenv_cfg}" } function check_and_fix_grub_cfg_symlink() { # Ensure that the symlink, such as /etc/grub2.cfg, exists and points to the correct file local symlink_path="${1}" local symlink_target="${2}" # Recreate the symlink if it does not exist, not actually a symlink or points to a wrong file if [[ ! -e "${symlink_path}" ]]; then echo "WARNING: ${symlink_path} does not exist, it should be a symlink pointing to ${symlink_target}" | tee -a "${log}" recreate_symlink "${symlink_path}" "${symlink_target}" elif [[ ( -f "${symlink_path}" && ! -L "${symlink_path}" ) \ || ( -L "${symlink_path}" && "$(readlink "${symlink_path}")" != "${symlink_target}" ) ]]; then echo "WARNING: invalid ${symlink_path}, it should be a symlink pointing to ${symlink_target}" | tee -a "${log}" recreate_symlink "${symlink_path}" "${symlink_target}" fi } function recreate_symlink() { local symlink_path="${1}" local file_path="${2}" local backup_path="${3:-${symlink_path}.bak}" echo "To ensure successful system loading after a reboot, the symlink will be recreated" if [[ -f "${symlink_path}" || -L "${symlink_path}" ]]; then echo "Original file will be saved as ${backup_path}" | tee -a "${log}" /bin/mv "${symlink_path}" "${backup_path}" | tee -a "${log}" fi ln -sf "${file_path}" "${symlink_path}" | tee -a "${log}" } function check_and_fix_grub_cfg() { local config_path="${1}" # Config file must exist and be a regular file (not symlink) if [[ -L "${config_path}" ]]; then echo "WARNING: invalid ${config_path}, it should be a regular file" | tee -a "${log}" echo "To ensure successful system loading after a reboot, the file will be recreated" | tee -a "${log}" echo "Original file will be saved as ${config_path}.bak" | tee -a "${log}" /bin/mv "${config_path}" "${config_path}.bak" | tee -a "${log}" fi if [[ ! -e "${config_path}" ]]; then grub2-mkconfig -o "${config_path}" | tee -a "${log}" fi } function check_and_fix_grubenv_cfg() { # Ensure that the file, such as /boot/grub2/grubenv, exists and is a regular file (not symlink) local config_path="${1}" if [[ -L "${config_path}" ]]; then echo "WARNING: invalid ${config_path}, it should be a regular file" | tee -a "${log}" echo "To ensure successful system loading after a reboot, the file will be recreated" | tee -a "${log}" echo "Original file will be saved as ${config_path}.bak" | tee -a "${log}" /bin/mv "${config_path}" "${config_path}.bak" | tee -a "${log}" fi # Attempt to restore a grubenv file if it does not exist by performing: # 1. grubby --set-default=/boot/<vmlinuz for the CL kernel> # 2. systemctl restart tuned if [[ ! -e "${config_path}" ]]; then echo "Creating ${config_path} ..." | tee -a "${log}" # grubby is required to create a grubenv file if [[ ! -e "$(which grubby)" ]]; then retry_wrapper "yum -y install grubby 2>&1 | tee -a ${log}" fi local cl_kernel cl_kernel=$(grubby --info=ALL 2>&1 | grep '^kernel=' | grep -v 'rescue\|debug' | grep '\.lve' | head -n1 | cut -d'=' -f2 | tr -d '"') if [[ -z "${cl_kernel}" ]]; then echo "WARNING: failed to detect CloudLinux kernel, creation of ${config_path} failed" | tee -a "${log}" echo "This may result in the system being unable to load after a reboot" | tee -a "${log}" echo "Please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" | tee -a "${log}" if [[ -e "${config_path}.bak" ]]; then echo "Restoring previous ${config_path} file" | tee -a "${log}" /bin/mv "${config_path}.bak" "${config_path}" | tee -a "${log}" fi else grubby --set-default="${cl_kernel}" | tee -a "${log}" /usr/bin/systemctl restart tuned | tee -a "${log}" fi fi } function vm_has_new_hardware() { #AuthenticAMD arch list: #23 Zen / Zen+ / Zen 2 #24 Hygon Dhyana #25 Zen 3 #GenuineIntel arch list: #Cooper Lake/Cascade Lake/ Skylake(Server) - Family 6 Model 85 #Ice Lake(Server) - Family 6 Model 108, Family 6 Model 106 #Broadwell(Server) - Family 6 Model 79, Family 6 Model 86 #Intel desktop CPUs: #Alder Lake - Family 6 Model 151, Family 6 Model 154 #Rocket Lake - Family 6 Model 167 #Tiger Lake - Family 6 Model 141, Family 6 Model 140 #Ice Lake (Client) - Family 6 Model 126, Family 6 Model 125 #Comet Lake - Family 6 Model 165, Family 6 Model 142 local intel_arch_list=("79" "85" "86" "106" "108" "125" "126" "142" "151" "154" "165") local amd_arch_list=("23" "24" "25") local vendor=$(grep -m1 ^"vendor_id" /proc/cpuinfo) local vendor_name=$(echo ${vendor} | awk '{print $3}') local cpu_family=$(grep -m1 ^"cpu family" /proc/cpuinfo | awk '{print $4}') local has_nvme=$(find /dev -type b -name 'nvme*') if [[ $has_nvme ]]; then return 0 fi if [[ "GenuineIntel" == "${vendor_name}" ]]; then for val in "${intel_arch_list[@]}"; do if [[ "${cpu_family}" == "${val}" ]]; then return 0 fi done return 1 fi if [[ "AuthenticAMD" == "${vendor_name}" ]]; then for val in "${amd_arch_list[@]}"; do if [[ "${cpu_family}" == "${val}" ]]; then return 0 fi done return 1 fi return 1 } function regenerate_grub_conf(){ local grub2_conf local grub2_efi_conf grub2_conf=$(readlink -f /etc/grub2.cfg) grub2_efi_conf=$(readlink -f /etc/grub2-efi.cfg) local default=/boot/grub2/grub.cfg local grub2_conf_found=false if [[ -e /etc/grub2.cfg && -e ${grub2_conf} ]]; then echo "${grub2_conf} found as grub config" | tee -a "${log}" grub2_conf_found=true grub2-mkconfig -o "${grub2_conf}" | tee -a "${log}" fi if [[ -e /sys/firmware/efi && -e /etc/grub2-efi.cfg && -e ${grub2_efi_conf} ]]; then echo "${grub2_efi_conf} found as grub config" | tee -a "${log}" grub2_conf_found=true grub2-mkconfig -o "${grub2_efi_conf}" | tee -a "${log}" fi if [[ "${grub2_conf_found}" == "false" ]]; then echo "No valid symlinks found! Default ${default} detected as grub config" | tee -a "${log}" grub2-mkconfig -o "${default}" | tee -a "${log}" fi } function check_convert_to_hybrid() { local message="Your server has new hardware. It will be automatically converted to CloudLinux 7 Hybrid which has a newer kernel" if ([[ "${no_force_hybridize}" == "false" && "7" == "${OS_VERSION}" ]] && vm_has_new_hardware) || ${hybridize}; then add_precheck_mandatory_change "$message" return 0 fi return 1 } function convert_cl7_to_cl7h_if_needed() { # We convert CL7 to CL7h if VM has the new hardware (see CLKRN-214) if check_convert_to_hybrid; then echo "Your server has new hardware. It will be automatically converted to CloudLinux 7 Hybrid which has a newer kernel" | tee -a "${log}" hybridize_attempted=true local rc if [[ "true" == "${test_updates}" ]]; then ENABLE_BETA_REPO="1" normal-to-hybrid else normal-to-hybrid fi rc=$? echo "You can find complete log of hybrid conversion process in /var/log/normal-to-hybrid.log" | tee -a "${log}" if [[ "$rc" -ne 0 ]]; then # normal-to-hybrid failed (commonly a transient repo or network problem). The system # has NOT been hybridized — the previously-installed CL7 kernel is still the default # boot entry. Suppress the "please reboot" prompt and abort so the user (or CI) sees # this as a real failure instead of silently shipping a half-converted system. echo "ERROR: normal-to-hybrid failed with exit code $rc — system has NOT been hybridized." | tee -a "${log}" echo "PLEASE DO NOT REBOOT. See /var/log/normal-to-hybrid.log for the underlying error." | tee -a "${log}" show_reboot_message=false exit "$rc" fi fi } function detect_distro() { os_name=$(rpm -q --qf %{name} $(rpm -q --whatprovides redhat-release) | awk -F- '{print $1}') if [[ "${os_name}" == "almalinux" ]]; then echo "AlmaLinuxOS" elif [[ "${os_name}" == "rocky" ]]; then echo "RockyLinux" elif [[ "${os_name}" == "cloudlinux" ]]; then echo "CloudLinux" elif [[ "${os_name}" == "centos" ]]; then echo "CentOS" else echo "unknown" fi } function check_boot_duplicates() { # Check that etc/fstab configuration is explicit about device mounting on boot/efi fstab_boot_efi=$(grep /boot/efi /etc/fstab) # Colors should be empty during precheck RED=$([ "$precheck" = "false" ] && echo '\033[0;31m' || echo '') NOCOLOR=$([ "$precheck" = "false" ] && echo '\033[0m' || echo '') if [ -n "$fstab_boot_efi" ]; then # get pattern (LABEL or UUID of device mounted on /boot/efi) # example (fstab_boot_efi -> pattern): # "LABEL=EFI_SYSPART /boot/efi vfat defaults 0 1" -> "EFI_SYSPART" # or # "UUID=999C-7B59 /boot/efi vfat defaults,uid=0,gid=0,umask=0077,shortname=winnt 0 0" -> "999C-7B59" pattern=$(echo "$fstab_boot_efi" | awk '{print $1}' | cut -d= -f2) # search for pattern duplicates in blkid blkid_pattern_count=$(blkid | grep "$pattern" | wc -l) local description="/etc/fstab configuration is explicit about device mounting on /boot/efi|/etc/fstab configuration is not explicit about device mounting on /boot/efi" local fix_tip="${RED}WARNING! Your /etc/fstab configuration is not explicit about device mounting on boot/efi. This is not a CL software issue but this potentially can cause problems with booting the CL kernel. It is strongly recommended to contact your hosting provider before proceeding. For details please read this article: https://cloudlinux.zendesk.com/hc/en-us/articles/360021620699 ${NOCOLOR}" local message_for_cli="If you're certain that your configuration is correct, please run this script again, adding this flag: --skip-boot-check" [ "$blkid_pattern_count" -ge 2 ] check_exit_code 1 "$description" "$fix_tip" "$message_for_cli" fi } function check_conversion_from_centos8() { # Block conversions from CentOS 8 and advices user to convert into AlmaLinux first local description="conversion will be performed from Almalinux|trying to perform conversion from CentOS" local fix_tip="Conversion from CentOS 8 and 9 is not supported. Instead, you can convert into AlmaLinux using the following script: https://github.com/AlmaLinux/almalinux-deploy" local message_for_cli="If you want to continue with conversion, rerun the script with --skip-os-check option, but in this case the consequences can be unpredictable, and the corporation does not bear any responsibility for the consequences of such a launch. We strongly recommend that you do not attempt to convert production servers with this script" [[ "$(detect_distro)" == "CentOS" ]] check_exit_code 1 "$description" "$fix_tip" "$message_for_cli" } function check_conversion_on_cloudlinux() { # Block cldeploy conversions on systems that are already CloudLinux, unless forced with skip-os-check # Uninstallation on CL is always allowed. if [[ "$uninstall" == "false" ]] && [[ "$skiposcheck" == "false" ]]; then local description="system is not already converted to CloudLinux|trying to perform conversion on a system that is already converted" local fix_tip="System is already CloudLinux, there is no need to perform a conversion." local message_for_cli="To continue the conversion anyway, you may run cldeploy with --skip-os-check option, but there are no guarantees that it won't cause any issues after the conversion." # Returns 0 if the system is CloudLinux, 1 otherwise os_is_CloudLinux check_exit_code 1 "$description" "$fix_tip" "$message_for_cli" fi } function is_root() { [ $(id -u) -eq 0 ] return $? } function check_cl_release_available() { # return 1 if base OS release > last available CloudLinux release, 0 otherwise rpm --import "${PUBLIC_REPO_URL}/cloudlinux/security/RPM-GPG-KEY-CloudLinux" 2>/dev/null LAST_CL_VERSION="$(rpm -qp ${CLOUDLINUX_RELEASE} --qf %{version} 2>/dev/null | cut -d. -f1)" LAST_CL_RELEASE="$(rpm -qp ${CLOUDLINUX_RELEASE} --qf %{version} 2>/dev/null | cut -d. -f2)" echo "Last available CloudLinux release: $LAST_CL_VERSION.$LAST_CL_RELEASE" | tee -a "${log}" echo "Current system release: $OS_VERSION.$OS_RELEASE" | tee -a "${log}" # If LAST_CL_RELEASE is empty, the rpm query failed - this can happen if the URL is incorrect or unreachable local description="Detected CloudLinux release $LAST_CL_VERSION.$LAST_CL_RELEASE|Last CloudLinux release unknown - conversion cannot proceed" local fix_tip="Check whether the CloudLinux release package URL is correct and reachable (${CLOUDLINUX_RELEASE})" [[ -n "$LAST_CL_RELEASE" ]] ! check_exit_code 0 "$description" "$fix_tip" && exit 1 if [[ "$OS_VERSION" -gt "$LAST_CL_VERSION" ]]; then return 1 elif [[ ! -z "$LAST_CL_RELEASE" && "$OS_VERSION" -eq "$LAST_CL_VERSION" ]]; then if [[ "$OS_RELEASE" -le "$LAST_CL_RELEASE" ]]; then return 0 elif [[ "$OS_RELEASE" -eq "$((LAST_CL_RELEASE+1))" && "$INSTALL_LOWER_VERSION" == "true" ]]; then return 0 elif [[ "$(detect_distro)" = "CentOS" && "$OS_VERSION" = "7" && -z "$OS_RELEASE" ]]; then return 0 else return 1 fi else return 0 fi } function check_install_lower_version() { # Allow conversion with downgrade only on AlmaLinux 8 and 9 (CL10+ wouldn't have mirrors) if [[ "$(detect_distro)" == "AlmaLinuxOS" && ( "$OS_VERSION" -eq "8" || "$OS_VERSION" -eq "9" ) ]]; then # This env variable forces the downgrade. Intended for testing. if [[ $CLDEPLOY_TEST_SET_LOWER_VERSION_AS_CURRENT == "true" ]]; then current_cl_release_rpm_uri_dir="${CURRENT_REPO_URL}/cloudlinux/${LOWER_VERSION_RELEASE}/BaseOS/x86_64/os/Packages/" current_cl_release_rpm=$(curl -L "${current_cl_release_rpm_uri_dir}" 2>/dev/null | sed -n "s/^.*\(cloudlinux-release.*rpm\).*$/\1/p" | head -1) current_cl_release_rpm_uri="${current_cl_release_rpm_uri_dir}${current_cl_release_rpm}" echo "Note: Using current_cl_release_rpm_uri ${current_cl_release_rpm_uri}" | tee -a "${log}" elif [[ -n "$CLOUDLINUX_RELEASE_URL" ]]; then current_cl_release_rpm_uri="$CLOUDLINUX_RELEASE_URL" else current_cl_release_rpm_uri="${CURRENT_REPO_URL}/cloudlinux/migrate/release-files/cloudlinux/${OS_VERSION}/x86_64/cloudlinux${OS_VERSION}-release-current.x86_64.rpm" fi current_cl_version_release=$(rpm -qp "${current_cl_release_rpm_uri}" --qf '%{version}' 2>/dev/null) current_cl_version=$(echo "$current_cl_version_release" | cut -d. -f1) current_cl_release=$(echo "$current_cl_version_release" | cut -d. -f2) if [[ $OS_VERSION -eq $current_cl_version && $OS_RELEASE -eq $((current_cl_release+1)) ]]; then if [[ -z "$PANEL" ]] || [[ "$PANEL" =~ ^(cpanel|plesk)$ ]]; then local distro distro="$(detect_distro)" local kernel_warning kernel_warning="" [[ "$OS_VERSION" -ge "9" ]] && kernel_warning="The kernel will be set to the version available on AlmaLinux ${LOWER_VERSION_RELEASE} to ensure CloudLinux kernel module (kmod-lve) compatibility." yesno "Your ${distro} release version is greater then the latest currently available CloudLinux release. You can either wait for a new version of CloudLinux, or install an older version of CloudLinux ${LOWER_VERSION_RELEASE} over your ${distro} installation. If you continue, your system will be downgraded to CloudLinux ${LOWER_VERSION_RELEASE}. The current versions of MySQL/MariaDB will be frozen in order to prevent problems during the downgrade. They will be unfrozen automatically during an upgrade to CloudLinux ${OS_VERSION}.${OS_RELEASE}. ${kernel_warning} When the newer CloudLinux ${OS_VERSION}.${OS_RELEASE} version is released, you will be able to install the corresponding 'cloudlinux-release' package to upgrade your system." if [ $ans -eq 0 ]; then echo "Exiting" | tee -a "${log}" rm -f $lock exit 1 fi INSTALL_LOWER_VERSION=true echo "Note: converting to CL version ${current_cl_version}.${current_cl_release}" | tee -a "${log}" else echo "Would attempt to convert to CL version ${current_cl_version}.${current_cl_release}" | tee -a "${log}" echo "Conversion with downgrade not supported on $PANEL - will not attempt to perform it. Conversion with downgrade is currently supported only for installations without panel or with one of the following panels: cPanel, Plesk." | tee -a "${log}" fi fi fi } function record_system_info() { local log="/var/log/cldeploy-debug.log" touch "$log" chmod 600 "$log" # Redact -k/--key and -t/--auth-token values from the getopt-normalized # $options string. getopt emits every short-option form (-kV, -k V, -k=V, # -yk V, --key=V, ...) as "-k 'VALUE'" / "--key 'VALUE'", so this catches # cluster forms BugBot flagged (e.g. `-yk MYKEY`). $options is set in the # main flow before record_system_info is called. local redacted_args redacted_args=$(echo "$options" | sed -E "s/((-k|--key|-t|--auth-token) +)'[^']*'/\1'***REDACTED***'/g") echo "===== $(date) =====" >> "$log" echo "Passed arguments: $redacted_args" >> "$log" uname -a >> "$log" 2>&1 rpm -qa >> "$log" 2>&1 echo >> "$log" } function is_cldeploy_running() { if [ -f "$lock" ]; then local proc_path proc_path="/proc/$(cat $lock)" [ -d "$proc_path" ] && grep -q cldeploy "${proc_path}/cmdline" return $? fi return 1 } function create_mode_file() { local mode="install" if [ "$uninstall" = "true" ]; then mode="uninstall" fi echo "$mode" > "$mode_file" } function clean_log() { [ ! -f "$log" ] && return 0 echo "$(cat $log)" >> "${log}.old" echo >> "${log}.old" echo "===== $(date) =====" > "$log" } function cleanup() { local exit_code=$? [ "${cldeploy_started:-false}" = "false" ] && exit $exit_code echo "$exit_code" > "$last_result_file" rm -f "$lock" exit $exit_code } function install_alt_els_repositories() { yum install -y els-php-release els-python-release els-nodejs-release els-ruby-release local exit_code=$? return $exit_code } os_is_CloudLinux(){ # Detect CloudLinux in both classic and subsystem modes if grep -q "CloudLinux" /etc/redhat-release 2>/dev/null; then echo "CloudLinux detected via /etc/redhat-release" | tee -a "${log}" return 0 fi if rpm -q cloudlinux-release >/dev/null 2>&1; then echo "CloudLinux release package detected" | tee -a "${log}" return 0 fi if command -v cldetect >/dev/null 2>&1; then if cldetect --detect-os 2>/dev/null | grep -qi "CloudLinux"; then echo "CloudLinux detected via cldetect" | tee -a "${log}" return 0 fi fi return 1 } function get_edition_from_key() { local RESULT RESULT=$(CLN_ACTIVATION_KEY="$2" $PYTHON_BIN -c ' import sys sys.path[:] = [entry for entry in sys.path if entry not in ("", ".", __import__("posix").getcwd())] import os cwd = os.path.realpath(os.getcwd()) sys.path[:] = [entry for entry in sys.path if os.path.realpath(entry) != cwd] import time import ssl try: import xmlrpc.client as xmlrpclib except ImportError: import xmlrpclib # NOTE: The original is contained in rhn-client-tools package # (at /usr/share/rhn/CLN-ORG-TRUSTED-SSL-CERT) and is # copy-pasted here to make RPC calls possible (and secure) # without installing the package. # It is valid till January 18, 2038 _CLN_CA_CERT = u"""-----BEGIN CERTIFICATE----- MIIFazCCBFOgAwIBAgIJAKtahcJblL0IMA0GCSqGSIb3DQEBBQUAMIG0MQswCQYD VQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTESMBAGA1UEBxMJUHJpbmNldG9u MRgwFgYDVQQKEw9DbG91ZExpbnV4IEluYy4xGzAZBgNVBAsTEkNsb3VkTGludXgg TmV0d29yazEiMCAGA1UEAxMZQ0xOIENlcnRpZmljYXRlIEF1dGhvcml0eTEhMB8G CSqGSIb3DQEJARYSY2xuQGNsb3VkbGludXguY29tMB4XDTEwMDIxOTExNTg0NloX DTM4MDExODExNTg0NlowgbQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVy c2V5MRIwEAYDVQQHEwlQcmluY2V0b24xGDAWBgNVBAoTD0Nsb3VkTGludXggSW5j LjEbMBkGA1UECxMSQ2xvdWRMaW51eCBOZXR3b3JrMSIwIAYDVQQDExlDTE4gQ2Vy dGlmaWNhdGUgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJjbG5AY2xvdWRsaW51 eC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCyILpSMcptGxt1 yyUaxo861Js+yf+yIXdLKnOaNWpedUqOBu1amMkJk70rhep2R1OAYAe60cbuC8zm IZuWUF+MimrysiKDJxwvxc8+Z/uZ+6/KVv5rOrPdha+UrB0A57j58UrFrC8OHUxC o6g6zXplXNpRB8iEkhwhXPvRDmZOfk0UulRBJvn7bEa2LwM1bRuJ14wL64UQImjl gGomnbsw6RasDFNUEKQz94dIB3eL1L3zWYUoyzzuYeyztsVvhH/7erhTZy/ws8ma XaHUbD8Ez8VMA8eqKM8BkLblP35NYJaGqRq81FMzA4Edz5BPU1DJJrYw+oTHnoN3 gOc/fuPpAgMBAAGjggF8MIIBeDAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwICpDAd BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwMQYJYIZIAYb4QgENBCQWIlJI TiBTU0wgVG9vbCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFDql2L5O 4KGwhj4JlDaYfTtPR8mOMIHpBgNVHSMEgeEwgd6AFDql2L5O4KGwhj4JlDaYfTtP R8mOoYG6pIG3MIG0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTES MBAGA1UEBxMJUHJpbmNldG9uMRgwFgYDVQQKEw9DbG91ZExpbnV4IEluYy4xGzAZ BgNVBAsTEkNsb3VkTGludXggTmV0d29yazEiMCAGA1UEAxMZQ0xOIENlcnRpZmlj YXRlIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJARYSY2xuQGNsb3VkbGludXguY29t ggkAq1qFwluUvQgwDQYJKoZIhvcNAQEFBQADggEBAIJ+Nrg4SCqEGE86SfhVeqst WuJtlddUqsyAvr1otB/L7UnZ4j85QQKrRdei7OWe8eRTcG+6BdetLL0/jgobDVkm g5q53e+9kWsdf4+JiLG2MPgROHQgRQXmOKt9jEy1V2mlQOPOQrkUiV87wQT8GQb5 w4Scb7Gwibb9qEI7qmKBAaUBA5vM2GvZ4EVExzAy3rRWdpU+wGAQImCXi2UychqF HNKbRFL9jIZtcghISvfGvbWiJyuMVmn8IL6Qxo8fjY1cuUBv/jpMbkfsvbdlhkf3 5WTKBU0qRsFiLiAcvdvbu358OX1Llhss5epZKj4zafS6fZDenxPvGIh39KSg4Wg= -----END CERTIFICATE-----""" def main(url, key): client_kwargs = {} try: client_kwargs["context"] = ssl.create_default_context( cadata=_CLN_CA_CERT ) except AttributeError: raise RuntimeError( "TLS certificate verification is unavailable; " "update the system Python packages and rerun cldeploy" ) client = xmlrpclib.ServerProxy(url, **client_kwargs) for attempt in range(1, 6): try: return client.registration.license_check(key)["edition"].lower() except (xmlrpclib.Fault, KeyError) as e: raise e except Exception as e: print("Retry CLN RPC request attempt {} failed: {}".format(attempt, e)) time.sleep(attempt) raise Exception("Failed after all retries") try: print(main(sys.argv[1], os.environ["CLN_ACTIVATION_KEY"])) except Exception as e: print("CLN RPC request error: {}".format(e)) exit(1) ' "$1") local STATUS=$? if [[ $STATUS -ne 0 ]]; then echo "$RESULT" >> "$log" echo "$RESULT" >&2 return 1 fi echo "$RESULT" } trap "cleanup" EXIT trap "exit $?" INT is_root [ $? -ne 0 ] && echo "Please run cldeploy as root" && exit 1 init_vars $0 options=$(getopt -o cmik:a:t:y -l uninstall,regenmodprobeconf,force-hybridize,no-force-hybridize,to-solo-edition,to-admin-edition,to-container-environment,force-packages-installation,unregistered-core-packages,components-only,conversion-only,hostinglimits,skip-kmod-check,skip-boot-check,help,byip,skip-version-check,skip-os-check,skip-ea4-script-download,skip-registration,beta,alt-repo:,centos-repo:,auth-token:,testing-repos,noninteractive,precheck,serverurl:,key:,base-repo-url:,addon-repo-urls: -- "$@") if [ $? != 0 ] ; then print_help ; exit 1 ; fi eval set -- "$options" while true; do case $1 in --help) print_help exit 0 ;; --precheck) precheck=true log=$precheck_log > $log shift ;; -c|--uninstall) uninstall=true shift ;; --force-hybridize) hybridize=true shift ;; --no-force-hybridize) no_force_hybridize=true shift ;; --to-solo-edition) cl_solo_edition=true check_solo_conversion_supported shift ;; --to-admin-edition) cl_admin_edition=true check_admin_conversion_supported shift ;; --to-container-environment) if [[ -f "${OPEN_VZ_MARKER}" ]]; then cl_container=true fi shift ;; --force-packages-installation) force_packages_installation=true shift ;; --unregistered-core-packages) unregistered_core_packages=true shift ;; -k|--key) conversion=true activationkey=$2 shift 2 ;; -i|--byip) conversion=true activationkey="" shift ;; -m|--regenmodprobeconf) regen_modprobe_conf=true shift ;; --components-only) components=true shift ;; --conversion-only) conversiononly=true shift ;; --hostinglimits) hostinglimits=true shift ;; --skip-kmod-check) skipkmodcheck=true shift ;; --skip-boot-check) skipbootcheck=true shift ;; --skip-version-check) skipversioncheck=true shift ;; --skip-os-check) skiposcheck=true shift ;; --skip-ea4-script-download) skip_ea4_script_download=true shift ;; --serverurl) serverurl=$2 shift 2 ;; --skip-registration) registration=false shift ;; --beta) beta=true shift ;; -a|--alt-repo) validate_external_input build-id "--alt-repo" "$2" build_ids+=($2) shift 2 ;; --centos-repo) validate_external_input build-id "--centos-repo" "$2" build_centos_ids+=($2) shift 2 ;; --base-repo-url) validate_external_input repo-url "--base-repo-url" "$2" base_repo_url=($2) shift 2 ;; --base-repo-no-sslverify) base_repo_no_sslverify=true shift ;; --addon-repo-urls) IFS_BAK="${IFS}" IFS=',' read -r -a addon_repo_urls <<< "${2}" IFS="${IFS_BAK}" unset IFS_BAK for repo_url in "${addon_repo_urls[@]}"; do validate_external_input repo-url "--addon-repo-urls" "${repo_url}"; done # yum-config-manager get repo's name truncating http(s):// and replacing / to _ in repo's url for repo_url in "${addon_repo_urls[@]}"; do addon_repo_names+=("$(echo ${repo_url##http://} | tr / _)"); done shift 2 ;; -t|--auth-token) validate_external_input auth-token "--auth-token" "$2" auth_token=$2 shift 2 ;; --testing-repos) test_updates=true shift ;; -y|--noninteractive) noninteractive=true shift ;; --) shift break ;; -*) echo "$0: error - unrecognized option $1" 1>&2 print_help exit 1 ;; *) echo "Internal error!" ; exit 1 ;; esac done # Off-argv secret intake: accept the activation key / build-system auth token # from the environment when not supplied on the command line, so the secret # stays out of this process's world-readable /proc/<pid>/cmdline. Argv always # wins; CLDEPLOY_ACTIVATION_KEY is adopted only for a genuine key-registering # conversion -- it is ignored when -k/--key or -i/--byip already selected a # registration path (conversion=true), and equally when a non-conversion / # no-registration mode was explicitly selected (--components-only sets # components=true, --uninstall sets uninstall=true, --skip-registration sets # registration=false), so an ambient env key cannot silently turn those runs # into a conversion + CLN registration. if [[ "$conversion" != "true" && "$components" != "true" && "$uninstall" != "true" \ && "$registration" == "true" && -n "${CLDEPLOY_ACTIVATION_KEY:-}" ]]; then activationkey="$CLDEPLOY_ACTIVATION_KEY" conversion=true fi if [[ -z "$auth_token" && -n "${CLDEPLOY_AUTH_TOKEN:-}" ]]; then auth_token="$CLDEPLOY_AUTH_TOKEN" fi # ============================================================================= # MAIN EXECUTION FLOW - STEP 1: Initial checks and setup # ============================================================================= check_conversion_on_cloudlinux # ============================================================================= # MAIN EXECUTION FLOW - STEP 2: Activation key processing # ============================================================================= if [[ -n $activationkey ]]; then EDITION=$(get_edition_from_key $serverurl $activationkey) check_exit_code 0 "CloudLinux edition is successfully detected from the key|failed to detect CloudLinux edition from the key" \ "An attempt to detect the CloudLinux edition from the provided key has failed. Please ensure that the correct key was used without any misspellings or typographical errors. If the preceding message reports that TLS certificate verification is unavailable, update the system Python packages and rerun cldeploy. If you are absolutely certain that the key is correct, contact CloudLinux support at https://cloudlinux.zendesk.com/" case $EDITION in "solo") solo_activation_key=true ;; "admin") admin_activation_key=true ;; *) ;; esac fi # ============================================================================= # MAIN EXECUTION FLOW - STEP 3: Process locking and initialization # ============================================================================= is_cldeploy_running ! check_exit_code 1 "conversion to CloudLinux is not running|conversion to CloudLinux is running right now" \ "It is detected that another conversion process is running on the server right now. Only one CloudLinux conversion process can run at a time." && exit 0 # exit during precheck if conversion is already running if [ "$precheck" = "false" ]; then echo $$ > $lock cldeploy_started=true create_mode_file clean_log fi # ============================================================================= # MAIN EXECUTION FLOW - STEP 4: System compatibility checks # ============================================================================= check_panel check_panel_features check_install_lower_version check_release check_system_supported # ============================================================================= # MAIN EXECUTION FLOW - STEP 5: Edition-specific checks # ============================================================================= if [[ "$admin_activation_key" == "true" ]]; then check_admin_conversion_supported fi if [[ "$solo_activation_key" == "true" ]]; then check_solo_conversion_supported fi # ============================================================================= # MAIN EXECUTION FLOW - STEP 6: Environment and package manager checks # ============================================================================= check_digitalocean # check_linode_kvm if [[ "$OS_VERSION" -ge "8" ]]; then check_dnf else check_yum fi check_source check_convert_to_hybrid # ============================================================================= # MAIN EXECUTION FLOW - STEP 7: System requirements validation # ============================================================================= # Check system requirements before conversion and during precheck if [ "$conversion" = "true" ] || [ "$precheck" = "true" ]; then check_that_groups_clsupergid_and_clsudoers_are_empty if [ "$vzbeta" != "true" ]; then check_kernel_update_permission fi fi # ============================================================================= # MAIN EXECUTION FLOW - STEP 8: Additional compatibility checks # ============================================================================= if [[ "$OS_VERSION" -ge "8" ]] && [[ "$skiposcheck" == "false" ]] && [[ "$uninstall" == "false" ]]; then check_conversion_from_centos8 fi if [[ "$skipbootcheck" == "false" ]]; then check_boot_duplicates fi # ============================================================================= # MAIN EXECUTION FLOW - STEP 9: Precheck exit point # ============================================================================= [ "$precheck" = "true" ] && exit 0 # ============================================================================= # MAIN EXECUTION FLOW - STEP 10: Parameter validation # ============================================================================= if { [ -n "${build_ids[*]}" ] || [ -n "${build_centos_ids[*]}" ]; } && [ -z "$auth_token" ]; then echo "Specify buildsystem auth token" exit 1 fi if [ "$skipversioncheck" = "false" ]; then check_script_version "$@" fi if [[ "${no_force_hybridize}" = "true" && "${hybridize}" = "true" ]]; then echo "Passing both --force-hybridize and --no-force-hybridize is not allowed." | tee -a "${log}" echo "Please, specify only one of those options if needed." | tee -a "${log}" rm -f $lock exit 1 fi # ============================================================================= # MAIN EXECUTION FLOW - STEP 11: System information recording # ============================================================================= # Record information to /var/log/cldeploy-debug.log about system before conversion starts # to simplify debug in case of error record_system_info # ============================================================================= # MAIN EXECUTION FLOW - STEP 12: Boot configuration preparation # ============================================================================= check_and_fix_grub_efi_cfg remove_unified_cgroup_hierarchy_from_grub # ============================================================================= # MAIN EXECUTION FLOW - STEP 13: Operation mode validation # ============================================================================= if [ "$conversion" = "true" ] && [ "$uninstall" = "true" ] ; then echo "invalid combination"; rm -f $lock; exit 1; fi if [ "$conversion" = "false" ] && [ "$components" = "false" ] && [ "$uninstall" = "false" ] ; then echo "Nothing to do, please select an option" rm -f $lock exit 1 fi if [ "$conversion" = "true" ] && [ "$conversiononly" = "false" ] && [ "$components" = "false" ] ; then components=true fi if [ "$components" = "true" ] ; then hostinglimits=true; fi if [ "$OS_VERSION" -eq "9" ]; then # enable UsePAM if disabled enable_use_pam fi # ============================================================================= # MAIN EXECUTION FLOW - STEP 14: Core operations execution # ============================================================================= # echo conversion=$conversion # echo components=$components # ============================================================================= # MAIN EXECUTION FLOW - STEP 14A: Uninstall operation # ============================================================================= # UNINSTALL if [[ ${uninstall} == "true" ]]; then if [[ -d "${BACKUP}" ]]; then if ls "${BACKUP}" | grep "Rocky" &> /dev/null; then downgrade_to="RockyLinux" echo "RockyLinux is detected to be installed before CloudLinux instalation" | tee -a "${log}" echo "Unfortunately automatic uninstall for ${downgrade_to} is not possible." | tee -a "${log}" echo "Reinstall you server from scratch." | tee -a "${log}" exit 1 fi fi if [[ "cpanel" == "${PANEL}" ]] ; then if [ "$OS_VERSION" -eq "6" ] && [ "$CPANEL_MAJOR" -ge 88 ] ; then yesno "You are running cPanel & WHM version 88 or higher. These versions do not support CentOS 6 and uninstalling CloudLinux 6 on them will result in broken cPanel & WHM licenses." if [ $ans -eq 0 ]; then exit 0 fi fi if [[ -f /etc/cpanel/ea4/is_ea4 ]] ; then echo "Downloading the 'cloudlinux_ea3_to_ea4' script" pushd ~ > /dev/null || { echo "Failed to switch to homedir before downloading cloudlinux_ea3_to_ea4, exiting"; exit 1; } if [[ "$skip_ea4_script_download" == "false" ]]; then rm -f ./cloudlinux_ea3_to_ea4 wget "${PUBLIC_REPO_URL}/cloudlinux/sources/cloudlinux_ea3_to_ea4" 2>&1 | tee -a "${log}" fi if [[ -f ./cloudlinux_ea3_to_ea4 ]]; then sh ./cloudlinux_ea3_to_ea4 --restore-cpanel-ea4-repo 2>&1 | tee -a "${log}" /scripts/restartsrv_httpd 2>&1 | tee -a "${log}" else echo "Failed to download cloudlinux_ea3_to_ea4. Failed to restore cPanel EasyApache4" 2>&1 | tee -a "${log}" fi popd > /dev/null || { echo "Failed to popd to previous directory, continuing as is"; } fi fi if [[ -f /usr/sbin/cagefsctl ]] ; then echo "cagefs found, erasing" 2>&1 | tee -a "${log}" /usr/sbin/cagefsctl --do-not-ask --remove-all yum -y erase cagefs cagefs-safebin bsock bsock-libs 2>&1 | tee -a "${log}" fi if [[ -f /usr/sbin/db_governor ]]; then if [[ -f /usr/share/lve/dbgovernor/mysqlgovernor.py ]]; then echo "db-governor installed, erasing" 2>&1 | tee -a "${log}" /usr/share/lve/dbgovernor/mysqlgovernor.py --delete 2>&1 | tee -a "${log}" fi fi if ls /opt/alt/php*/usr/bin/php > /dev/null 2>&1 ; then echo "alt-php installed, erasing" 2>&1 | tee -a "${log}" yum -y groupremove alt-php 2>&1 | tee -a "${log}" fi if ls /opt/alt/python*/bin/python > /dev/null 2>&1; then echo "alt-python installed, erasing" 2>&1 | tee -a "${log}" yum -y erase alt-python* 2>&1 | tee -a "${log}" fi if [[ -f /usr/share/l.v.e-manager/install-lvemanager-plugin.py ]]; then echo "lvemanager installed, erasing" 2>&1 | tee -a "${log}" yum -y erase lvemanager 2>&1 | tee -a "${log}" fi # in case CL Solo meta package installed if [[ -f /etc/cloudlinux-edition-solo ]]; then echo "cloudlinux-solo-meta package detected, erasing" 2>&1 | tee -a "${log}" # https://stackoverflow.com/questions/15799047/trying-to-remove-yum-which-is-protected-in-centos rpm -e --nodeps "${CL_SOLO_META_PACKAGE}" 2>&1 | tee -a "${log}" fi # in case CL Admin meta package installed if [[ -f /etc/cloudlinux-edition-admin ]]; then echo "cloudlinux-admin-meta package detected, erasing" 2>&1 | tee -a "${log}" # https://stackoverflow.com/questions/15799047/trying-to-remove-yum-which-is-protected-in-centos rpm -e --nodeps "${CL_ADMIN_META_PACKAGE}" 2>&1 | tee -a "${log}" fi # in case CL Container meta package installed if [[ -f /etc/cloudlinux-container ]]; then echo "cloudlinux-container-meta package detected, erasing" 2>&1 | tee -a "${log}" # https://stackoverflow.com/questions/15799047/trying-to-remove-yum-which-is-protected-in-centos rpm -e --nodeps "${CL_CONTAINER_META_PACKAGE}" 2>&1 | tee -a "${log}" fi if [[ -d "${BACKUP}" ]]; then if ls "${BACKUP}" | grep "almalinux" &> /dev/null; then downgrade_to="AlmaLinuxOS" echo "AlmaLinuxOS is detected to be installed" | tee -a "${log}" else downgrade_to="CentOS" echo "CentOS is detected to be installed" | tee -a "${log}" fi else downgrade_to="AlmaLinuxOS" # install centos for < 8.3 and for cpanel/plesk (currently do not support AlmaLinux) if [[ "${OS_VERSION}" -lt 8 || "8" == "${OS_VERSION}" && "${OS_RELEASE}" -lt 3 || "${PANEL}" == "plesk" || "${PANEL}" == "cpanel" ]]; then downgrade_to="CentOS" elif [[ "8" == "${OS_VERSION}" && "${OS_RELEASE}" -ge 3 ]]; then yesno "Your Cloudlinux version is 8.3 or higher. That means that AlmaLinux OS could be installed instead of CentOS. Select 'yes' if you want to install AlmaLinux OS, 'no' for CentOS." [ $ans -eq 0 ] && downgrade_to="CentOS" fi fi if [[ "${downgrade_to}" == "CentOS" ]]; then rpm --import http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-5 2>&1 | tee -a "${log}" rpm -ivh "${CENTOS_RELEASE}" --force --nodeps 2>&1 | tee -a "${log}" if [[ "${OS_VERSION}" -ge "8" ]]; then rpm -ivh "${CENTOS_GPG_KEYS}" --force --nodeps 2>&1 | tee -a "${log}" rpm -ivh "${CENTOS_REPOS}" --force --nodeps 2>&1 | tee -a "${log}" fi retry_wrapper "yum -y install centos-release-notes 2>&1 | tee -a ${log}" elif [[ "${downgrade_to}" == "AlmaLinuxOS" ]]; then rpm --import "${ALMALINUX_REPO_URL}/almalinux/RPM-GPG-KEY-AlmaLinux" 2>&1 | tee -a "${log}" rpm -ivh "${ALMALINUX_RELEASE}" --force --nodeps 2>&1 | tee -a "${log}" fi rpm -e --nodeps cloudlinux-release 2>&1 | tee -a "${log}" rpm -e --nodeps cloudlinux-ea4-release 2>&1 | tee -a "${log}" rpm -e --nodeps pam_lve 2>&1 | tee -a "${log}" rpm -e --nodeps cloudlinux-linksafe 2>&1 | tee -a "${log}" erase_package_via_rpm rhn-setup-gnome 2>&1 | tee -a "${log}" # rhn-client-tools 3.0+ absorbs rhnsd and rhnlib — filter to installed # packages so the batch rpm -e does not abort on missing ones. rhn_pkgs_to_erase=() for pkg in rhn-client-tools rhn-check rhnsd rhn-setup rhnlib yum-rhn-plugin; do rpm -q "$pkg" &>/dev/null && rhn_pkgs_to_erase+=("$pkg") done if [[ ${#rhn_pkgs_to_erase[@]} -gt 0 ]]; then rpm -e "${rhn_pkgs_to_erase[@]}" 2>&1 | tee -a "${log}" fi generate_sysinfo_cpanel xz_rpm=$(rpm -q xz) if echo ${xz_rpm} | grep cloudlinux ; then # downgrade xz rpm packages to centos versions, see CLDEPLOY-149 yum -y downgrade xz xz-libs xz-devel 2>&1 | tee -a "${log}" fi echo -e "\e[1m\e[31m" echo "You converted back to ${downgrade_to}" | tee -a "${log}" echo "Now is the time to install kernel." | tee -a "${log}" echo -e "To delete CloudLinux kernel do \nrpm -e --nodeps $(rpm -qa | grep ^kernel | grep lve | tr -s '\n' ' ')" echo "To install new ${downgrade_to} kernel once you deleted CloudLinux kernel, type yum install kernel" | tee -a "${log}" echo "If yum says that the latest kernel is already installed - it\'s OK" | tee -a "${log}" echo "Please check your bootloader configuration before rebooting the system" | tee -a "${log}" echo -e "To remove unused kmods and lve libs do \nyum remove lve kmod*lve*" echo "Also some CloudLinux packages weren't removed automatically," echo "because it can lead to the problems with excludes, dependencies, protected packages" echo "or something else. You can find the remained packages using the command" echo "rpm -qa --queryformat '%{name}-%{version}-%{release} %{vendor}\n' | grep CloudLinux" echo "And manually downgrade them to upstream packages if ones exist in the upstream repositories" echo "or remove them if packages exist only in the CloudLinux repositories." echo "You can contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" echo "if you still have questions. Thank you for using our product." echo -e "\e[0m" rm -f "${lock}" exit 0 fi # ============================================================================= # MAIN EXECUTION FLOW - STEP 14B: Conversion operation # ============================================================================= if [ "$conversion" = "true" ] ; then # ============================================================================= # MAIN EXECUTION FLOW - STEP 14B.1: Pre-conversion cleanup # ============================================================================= if [ "$remove_non_standard_kernels" = "true" ]; then echo "Removing non-standard kernels from RPM database" | tee -a "${log}" rpm -e --justdb $(rpm -qa | grep kernel | grep -v $KERNEL_VERSION) 2>&1 | tee -a "${log}" check_source fi # Allow to install core packages even with --skip-registration for CL10 if [ "$registration" = "true" ] || [ "${unregistered_core_packages}" = "true" ] ; then handle_els_packages backup prep fi check_ovh check_root_device_link yum clean all 2>&1 |& grep -v "${ROLLOUT_WARNING_FILTER}" | tee -a "${log}" if rpm -qf --queryformat "%{name}" /lib/modules/"$(uname -r)" > /dev/null 2>&1 ; then KERNEL=$(rpm -qf --queryformat "%{name} " /lib/modules/"$(uname -r)") else KERNEL="kernel" fi if [ "$OS_VERSION" -eq "5" ] && [ "$LINODE" = "true" ]; then KERNEL="kernel-xen" fi echo "kernel flavour $KERNEL" >> $log # kmod-lve must be in the transaction to prevent kmod-lve-lts from being pulled instead. # Both packages provide `namespace` (required by lve), so we must explicitly request kmod-lve. # Exception: CL9 downgrade installs kernel and kmod-lve separately (see pre-installation step). if [[ "$OS_VERSION" -eq "9" && "$INSTALL_LOWER_VERSION" == "true" ]]; then # CL9 downgrade: Install kernel and kmod-lve separately to avoid protected package conflict. PKGS="lve lve-utils liblve liblve-devel lve-stats" elif [[ "$OS_VERSION" -eq "8" && "$INSTALL_LOWER_VERSION" == "true" ]]; then PKGS="$KERNEL lve kmod-lve lve-utils liblve liblve-devel lve-stats" else PKGS="$KERNEL cloudlinux-release lve kmod-lve lve-utils liblve liblve-devel lve-stats" fi # Install latest rhn-client-tools so the channel migration goes through. PKGS="$PKGS rhn-client-tools" SOLO_PACKAGES="${CL_SOLO_META_PACKAGE}" ADMIN_PACKAGES="${CL_ADMIN_META_PACKAGE}" CL_CONTAINER_PACKAGES="${CL_CONTAINER_META_PACKAGE}" SHARED_PACKAGES="pam_lve" if [[ "${solo_activation_key}" == "true" || "${cl_solo_edition}" == "true" ]]; then echo "CloudLinux Solo edition detected, going to install ${CL_SOLO_META_PACKAGE}" | tee -a "${log}" cl_solo_edition=true cl_edition="solo" PKGS="${SOLO_PACKAGES} ${PKGS}" elif [[ "${admin_activation_key}" == "true" || "${cl_admin_edition}" == "true" ]]; then echo "CloudLinux Admin edition detected, going to install ${CL_ADMIN_META_PACKAGE}" | tee -a "${log}" cl_admin_edition=true cl_edition="admin" PKGS="${ADMIN_PACKAGES} ${SHARED_PACKAGES} ${PKGS}" else cl_edition="shared" PKGS="${PKGS} ${SHARED_PACKAGES}" fi if [[ "${cl_container}" == "true" ]]; then echo "CloudLinux Container environment detected, going to install ${CL_CONTAINER_META_PACKAGE}" | tee -a "${log}" PKGS="${CL_CONTAINER_PACKAGES} ${PKGS}" fi # on cloudlinux 7 these modules are not builtin in kernel package if [[ "${OS_VERSION}" -eq "7" ]]; then PKGS="$PKGS kmod-ixgbe kmod-igb kmod-e1000e" fi if rpm -qa | grep -q kmod > /dev/null 2>&1 ; then for kmod in $(rpm -q --qf '%{name}\n' $(rpm -qa | grep ^kmod\-) | grep -v x86_64 | grep -v i686 | grep -e e1000e -e aacraid -e r8168 -e microsoft -e igb -e dell-dm-switch -e ixgbe); do rpm -e --justdb $kmod --nodeps PKGS="$PKGS $kmod" done fi if [ -d /sys/module/storvsc ] ; then PKGS="$PKGS microsoft-hyper-v" fi # upstream iproute package is not compatible with CL 7 kernel so we # need to upgrade it before reboot to prevent network issues. # See CLKRN-242 for details. if [ "$OS_VERSION" -eq "7" ] ; then PKGS="$PKGS iproute" fi if [ "$NEED_SOURCE" = "YES" ] ; then PKGS="$PKGS kernel-devel gcc make"; fi create_repos if [ "$registration" = "true" ] ; then # rhn-custom-info (from the EL8+ rhn-tools module) requires dnf-plugin-spacewalk, # which rhn-client-tools 3.0+ obsoletes. Erase it before installing rhn-client-tools # so the upgrade doesn't fail on the unsatisfied dependency. erase_package_via_yum rhn-custom-info 2>&1 | tee -a "${log}" # rhn-setup ships in different repos per OS, and the package manager itself # is refreshed from CL repos before the rhn-setup install so plugin loading # and CL repo handling are consistent. CL10's base dnf is already current, # so it skips the refresh. if [[ "$OS_VERSION" -le "7" ]]; then REGISTRATION_REPOS="--enablerepo=cloudlinux-updates" PKG_MGR_REFRESH="yum" elif [[ "$OS_VERSION" -le "9" ]]; then REGISTRATION_REPOS="--enablerepo=baseos --enablerepo=appstream" PKG_MGR_REFRESH="dnf" else REGISTRATION_REPOS="--enablerepo=baseos --enablerepo=appstream" PKG_MGR_REFRESH="" fi # CL7-9: also enable the CL server repo set up by cloudlinux-release — it carries # the current rhn-client-tools, so registration runs on the latest (JWT-capable) # rhn right away, like CL10 (where it is BASE_REPO). Older cloudlinux-release # builds do not ship the repo — skip it then, since the package manager # hard-fails on an unknown repo id in --enablerepo. if [[ "$OS_VERSION" -le "9" ]] && grep -qsF '[cloudlinux-$basearch-server-$releasever]' /etc/yum.repos.d/cloudlinux.repo; then REGISTRATION_REPOS="${REGISTRATION_REPOS} --enablerepo=cloudlinux-${ARCH}-server-${OS_VERSION}" fi # Linked test-build repos (-a/--alt-repo) are deliberately NOT enabled here: a build's # rhn-client-tools may require a cloudlinux-release newer than the installed one, which # would fail this pre-registration transaction. The build's rhn-client-tools is installed # later with the main $PKGS set, where the matching cloudlinux-release arrives in the # same transaction (see CLOS-4367 and CLOS-4643). To be revisited in CLOS-4715. # CL8 only: rhn-setup is gated behind the satellite-5-client dnf module # (CL7 has no modularity; CL9/CL10 ship rhn-setup directly). if [[ "$OS_VERSION" -eq "8" ]]; then retry_wrapper "yum -y --disablerepo=* --enablerepo=${BASE_REPO} ${REGISTRATION_REPOS} module enable satellite-5-client |& grep -v \"${ROLLOUT_WARNING_FILTER}\" 2>&1 | tee -a ${log}" fi # Refresh the package manager from CL repos before the rhn-setup install. if [[ -n "${PKG_MGR_REFRESH}" ]]; then retry_wrapper "yum -y --disablerepo=* --enablerepo=${BASE_REPO} ${REGISTRATION_REPOS} install ${PKG_MGR_REFRESH} |& grep -v \"${ROLLOUT_WARNING_FILTER}\" 2>&1 | tee -a ${log}" fi # Install rhn-setup. rhn-setup Requires rhn-client-tools, which obsoletes # the legacy CLN-channel package plugin (dnf-plugin-spacewalk on CL8+, # yum-rhn-plugin on CL7) — so this single transaction also carries the # SWNG channel migration. RHN_PKG="rhn-setup" retry_wrapper "yum -y --disablerepo=* --enablerepo=${BASE_REPO} ${REGISTRATION_REPOS} install ${RHN_PKG} |& grep -v \"${ROLLOUT_WARNING_FILTER}\" 2>&1 | tee -a ${log}" check_pipestatus 0 "Unable to install $RHN_PKG, please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" echo "Registering as CloudLinux ${cl_edition}" | tee -a "${log}" opts="--edition=${cl_edition}" if [[ "$OS_VERSION" -ge "8" ]]; then # systems below cl8 do not have any editions and do not know about them during registration # starting from rhn-check-2.11 we should pass --migrate-silently # in order to avoid interactive edition migration confirmation rhn_check_version=$(rpm -qv rhn-check | grep -oP '(\d+\.\d+)' | head -1) rhn_check_maj_ver=$(echo $rhn_check_version | cut -d. -f1) rhn_check_min_ver=$(echo $rhn_check_version | cut -d. -f2) if ! [[ $rhn_check_maj_ver -eq 2 && $rhn_check_min_ver -lt 11 ]]; then opts="--edition=auto --migrate-silently" fi if [[ "$CLDEPLOY_TESTING" == "1" ]]; then opts="$opts --debug" fi fi if [[ -n $activationkey ]]; then /usr/sbin/rhnreg_ks --activationkey "$activationkey" --serverUrl="$serverurl" $opts 2>&1 | tee -a "${log}" check_pipestatus 0 "Unable to register through the CLN server, please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" else /usr/sbin/clnreg_ks --serverUrl="$serverurl" $opts 2>&1 | tee -a "${log}" check_pipestatus 0 "Unable to register through the CLN server, please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" fi # fix grub symlink as early as possible to prevent .rpmnew files creation check_and_fix_almalinux_grub_symlink if [[ "$CLDEPLOY_TESTING" == "1" ]]; then # configure up2date mirrorURL directive to use local mirrorlist UP2DATE_CONF="/etc/sysconfig/rhn/up2date" SEARCH_PATTERN="mirrorURL=" REPLACEMENT_LINE="mirrorURL=file:///etc/mirrorlist" if grep -q "$SEARCH_PATTERN" "$UP2DATE_CONF"; then # mirrorURL directive found, replace the line sed -i "/$SEARCH_PATTERN/c\\$REPLACEMENT_LINE" "$UP2DATE_CONF" else # mirrorURL directive not found, add the line echo "$REPLACEMENT_LINE" >> "$UP2DATE_CONF" fi yum clean all fi check_cloudlinux_repos if [ $? -ne 0 ]; then echo "No valid repo in repolist output" | tee -a "${log}"; rm -f $lock; exit 1; fi echo "Success" | tee -a "${log}" fi if rpm -q openssl-1.0.1e-30.el6.8 > /dev/null 2>&1; then yum -y downgrade openssl-1.0.1e-30.el6_6.8 openssl-devel-1.0.1e-30.el6_6.8 openssl-perl-1.0.1e-30.el6_6.8 \ openssl-static-1.0.1e-30.el6_6.8 fi if rpm -q subscription-manager > /dev/null 2>&1; then echo "Uninstalling subscription-manager..." | tee -a "${log}" yum -y erase subscription-manager fi # get latest CL release version (guard if cloudlinux-release is not installed) if rpm -q cloudlinux-release >/dev/null 2>&1; then CL_RELEASE="$(rpm -q --qf '%{version}' cloudlinux-release | cut -d. -f2)" else # If not installed (e.g., --skip-registration early flow), avoid numeric comparison errors CL_RELEASE="${OS_RELEASE}" fi if [[ "${OS_RELEASE}" -gt "${CL_RELEASE}" ]]; then # upgrading kmod packages when conversion from greater OS version: e.g 8.4 -> 8.3 echo "Update kmod* from repos ${ENABLED_REPOS}" | tee -a "${log}" retry_wrapper "yum -y ${ENABLED_REPOS} update kmod* 2>&1 | tee -a ${log}" else if [ -e /sys/firmware/efi ]; then # we need to update to latest available (even in BETA) # the yum update below does not enable beta repos for transaction # I did not enable it there, because it breaks ea3_to_ea4 script, which is buggy # when --beta option passed (https://cloudlinux.atlassian.net/browse/AAP-466) # SO IT IS TEMPORARY UNTIL AAP-466 done echo "Updating grub2-efi packages.." | tee -a "${log}" yum -y $ENABLED_REPOS update grub2-efi 2>&1 | tee -a ${log} fi # just update when conversion from less/same OS version: e.g 8.3 -> 8.3 echo "Updating all packages.." | tee -a "${log}" retry_wrapper "yum -y update --exclude=kmod-lve-lts 2>&1 | tee -a ${log}" fi echo "Installing lve..." | tee -a "${log}" # CL9 downgrade: Pre-install the target kernel before kmod-lve. # kmod-lve requires the kernel it was built for. Installing them together fails # when the system has a newer kernel (kernel-core is protected). if [[ "$OS_VERSION" -eq "9" && "$INSTALL_LOWER_VERSION" == "true" ]]; then echo "Pre-installing CloudLinux ${LOWER_VERSION_RELEASE} kernel for kmod-lve compatibility..." | tee -a "${log}" # Temporarily set almalinux_releasever to target the correct kernel version echo "Note: Temporarily setting ${LOWER_VERSION_RELEASE} to /etc/dnf/vars/almalinux_releasever" | tee -a "${log}" echo "${LOWER_VERSION_RELEASE}" > /etc/dnf/vars/almalinux_releasever yum clean all # Install target kernel as additional kernel (multiple versions can coexist) retry_wrapper "yum -y --disablerepo='*' --disableexcludes=all --enablerepo=baseos install kernel-core kernel-modules-core 2>&1 | tee -a ${log}" check_pipestatus 0 "Unable to install CloudLinux ${LOWER_VERSION_RELEASE} kernel. Please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" # Reset almalinux_releasever back to current version echo "Note: Resetting $OS_VERSION.$OS_RELEASE to /etc/dnf/vars/almalinux_releasever" | tee -a "${log}" echo "$OS_VERSION.$OS_RELEASE" > /etc/dnf/vars/almalinux_releasever yum clean all # Install kmod-lve separately - it will find the matching kernel echo "Installing kmod-lve..." | tee -a "${log}" retry_wrapper "yum -y ${ENABLED_REPOS} --disableexcludes=all install kmod-lve 2>&1 | tee -a ${log}" check_pipestatus 0 "Unable to install kmod-lve. Please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" fi if [ "$OS_VERSION" = "5" ] && [ "$LINODE" = "true" ]; then cp /etc/modprobe.conf /etc/modprobe.conf.orig echo "alias scsi_hostadapter xenblk" > /etc/modprobe.conf echo "co:2345:respawn:/sbin/mingetty xvc0" >> /etc/inittab echo "xvc0" >> /etc/securetty echo "UPDATEDEFAULT=yes" > /etc/sysconfig/kernel echo "DEFAULTKERNEL=kernel-xen" >> /etc/sysconfig/kernel fi rpm -e --nodeps cpuspeed > /dev/null 2>&1 # CL10 IBT safety: block kmod-lve autoload before any lve package is installed, # so the package chain can't load the module on the still-IBT-active kernel and # panic the server. Removed at the end once the CloudLinux tuned profile is active. defer_kmodlve_autoload # INSTALL CORE CL PACKAGES if [[ "$OS_VERSION" -ge "8" ]]; then if [[ "${force_packages_installation}" == "true" ]]; then retry_wrapper "yum -y ${ENABLED_REPOS} --disableexcludes=all install $PKGS --allowerasing 2>&1 | tee -a ${log}" check_pipestatus 0 "Unable to install required packages, please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" else retry_wrapper "yum -y ${ENABLED_REPOS} --disableexcludes=all install $PKGS 2>&1 | tee -a ${log}" check_pipestatus 0 "Unable to install required packages, you may use --force-packages-installation option to automatically resolve dependencies and remove conflicting packages.\nPlease contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" fi else retry_wrapper "yum -y ${ENABLED_REPOS} --disableexcludes=all install $PKGS 2>&1 | tee -a ${log}" check_pipestatus 0 "Unable to install required packages, please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" fi if [[ "$OS_VERSION" -ge "7" ]]; then # syncing boot stack packages to be installed exactly from CL repos echo "Syncing boot stack packages: ${BOOT_STACK_PACKAGES} with CL repositories. This is needed, otherwise Secure Boot is not working" | tee -a "${log}" BOOT_STACK_SYNC_PARAMS="-y --disableexcludes=all ${ENABLED_REPOS} distro-sync ${BOOT_STACK_PACKAGES}" if [[ "$OS_VERSION" -eq "9" && "$INSTALL_LOWER_VERSION" == "true" ]]; then # use --allowerasing to downgrade packages that are not compatible with higher version kernel BOOT_STACK_SYNC_PARAMS="--allowerasing ${BOOT_STACK_SYNC_PARAMS}" fi retry_wrapper "yum ${BOOT_STACK_SYNC_PARAMS} 2>&1 | tee -a ${log}" echo "Syncing kernel packages with CL repositories" | tee -a "${log}" if [[ "$OS_VERSION" -ge "9" ]]; then if [[ "$OS_VERSION" -eq "9" && "$INSTALL_LOWER_VERSION" == "true" ]]; then # CL9 downgrade only (CL10+ does not support downgrade). # Kernel and kmod-lve already installed in pre-installation step. # Skip distro-sync and set target kernel as default boot entry. echo "Note: Skipping kernel distro-sync for downgrade (kernel already installed)" | tee -a "${log}" echo "Note: Setting ${LOWER_VERSION_RELEASE} kernel as default boot entry" | tee -a "${log}" KERNEL_VERSION_PATTERN="el${LOWER_VERSION_RELEASE//./_}" DEFAULT_KERNEL=$(ls /boot/vmlinuz-*${KERNEL_VERSION_PATTERN}* 2>/dev/null | head -1) if [[ -n "${DEFAULT_KERNEL}" ]]; then grubby --set-default="${DEFAULT_KERNEL}" 2>&1 | tee -a "${log}" echo "Note: Set ${DEFAULT_KERNEL} as default boot kernel" | tee -a "${log}" else echo "Warning: Could not find ${LOWER_VERSION_RELEASE} kernel to set as default" | tee -a "${log}" fi # we don't want to allow kernel upgrades to the latest on CL9 if downgrading, # because we want to keep them at the same version as the CL kmodlve kernel module, # which will be older than the most recent accessible Alma kernel in a downgrade scenario yum_exclude_packages "kernel*" else retry_wrapper "yum -y ${ENABLED_REPOS} --disableexcludes=all distro-sync kernel* kmod-lve 2>&1 | tee -a ${log}" fi elif [[ "true" == "${test_updates}" ]]; then retry_wrapper "yum -y ${ENABLED_REPOS} --disableexcludes=all distro-sync kernel* kmod-lve --setopt=cloudlinux-${ARCH}-server-${OS_VERSION}.exclude=kernel* --setopt=${ALMALINUX_BASE}.exclude=kernel* 2>&1 | tee -a ${log}" else retry_wrapper "yum -y ${ENABLED_REPOS} --disableexcludes=all distro-sync kernel* kmod-lve --setopt=${ALMALINUX_BASE}.exclude=kernel* 2>&1 | tee -a ${log}" fi fi apply_yum_excludes rpm -q cloudlinux-linksafe &> /dev/null if [ $? -eq 0 ]; then /usr/bin/cl-linksafe-reconfigure --convert 2>&1 | tee -a "${log}" fi if [ "$PANEL" == 'cpanel' ]; then generate_sysinfo_cpanel fi if [ "$OS_VERSION" = "7" ];then retry_wrapper "yum -y ${ENABLED_REPOS} update systemd 2>&1 | tee -a ${log}" fi if [ "$OS_VERSION" = "7" ] && [ "$LINODE_KVM" = "true" ]; then retry_wrapper "yum -y install grub2 2>&1 | tee -a ${log}" cat > /etc/default/grub << EOF GRUB_TIMEOUT=5 GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)" GRUB_DEFAULT=saved GRUB_DISABLE_SUBMENU=true GRUB_TERMINAL_OUTPUT="console" GRUB_DISABLE_RECOVERY="true" GRUB_DISABLE_LINUX_UUID="true" GRUB_CMDLINE_LINUX="crashkernel=auto console=tty1 console=ttyS0,19200n8" GRUB_SERIAL_COMMAND="serial --speed=19200 --unit=0 --word=8 --parity=no --stop=1" EOF ln -s /boot/grub2 /boot/grub grub2-mkconfig -o /boot/grub2/grub.cfg 2>&1 | tee -a "${log}" fi if [[ "${cl_container}" != "true" && "$OS_VERSION" -ge "8" ]]; then if add_parameter_to_default_grub_cfg "GRUB_ENABLE_BLSCFG" "true"; then regenerate_grub_conf BLSCFG_CHANGED=true fi fi if [ "$OS_VERSION" = "6" ] && [ "$LINODE_KVM" = "true" ]; then retry_wrapper "yum -y install grub 2>&1 | tee -a ${log}" KVERSION=$(python -c 'import glob, re, rpm; print "%s-%s.%s" % sorted([(h["version"], h["release"], h["arch"]) for h in rpm.TransactionSet().dbMatch(rpm.RPMTAG_NAME, "kernel")], cmp=lambda b, a: rpm.labelCompare(("0", a[0], a[1]), ("0", b[0], b[1])))[0]') cat > /boot/grub/grub.conf << EOF default=0 timeout=5 title CloudLinux Server ($KVERSION) root (hd0) kernel /boot/vmlinuz-$KVERSION root=/dev/sda ro initrd /boot/initramfs-$KVERSION.img EOF ln -sf /boot/grub/grub.conf /boot/grub/menu.lst ln -sf /boot/grub/grub.conf /etc/grub.conf fi fi if [[ "true" == "${components}" ]]; then retry_wrapper "yum -y ${ENABLED_REPOS} install lvemanager 2>&1 | tee -a ${log}" check_pipestatus 0 "Unable to install lvemanager package, please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" if rpm -q apr &> /dev/null; then retry_wrapper "yum -y ${ENABLED_REPOS} update apr 2>&1 | tee -a ${log}" else retry_wrapper "yum -y ${ENABLED_REPOS} install apr 2>&1 | tee -a ${log}" fi check_pipestatus 0 "Unable to install/update apr package, please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" fi if [ "$vzbeta" = "true" ] ; then retry_wrapper "yum -y ${ENABLED_REPOS} install lve-utils cagefs | tee -a ${log}" fi # https://cloudlinux.atlassian.net/browse/LU-2268 # ensure we really need to install hostinglimits if [ "$hostinglimits" = "true" ] ; then if [ "$PANEL" = "ispmanager" ] || [ "$PANEL" = "interworx" ] ; then echo "Installing mod_hostinglimits" 2>&1 | tee -a "${log}" retry_wrapper "yum -y install mod_hostinglimits 2>&1 | tee -a ${log}" check_pipestatus 0 "mod_hostinglimits install failed, please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" fi if [ "$PANEL" = "plesk" ] ; then if [ "$PLESK_OLD" = "YES" ] ; then if rpm -q psa-mod_fcgid > /dev/null 2>&1; then echo "Replacing mod_fcgid..." 2>&1 | tee -a "${log}" rpm -e --nodeps psa-mod-fcgid-configurator 2>&1 | tee -a "${log}" rpm -e --nodeps psa-mod_fcgid 2>&1 | tee -a "${log}" retry_wrapper "yum -y install mod_fcgid 2>&1 | tee -a ${log}" fi fi if rpm -q --quiet "${CL_SOLO_META_PACKAGE}"; then echo "mod_hostinglimits installation skipped: Solo edition detected" else echo "Installing mod_hostinglimits" 2>&1 | tee -a "${log}" retry_wrapper "yum -y install mod_hostinglimits 2>&1 | tee -a ${log}" check_pipestatus 0 "mod_hostinglimits install failed, please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" fi fi # Note: EasyApache3 (EA3) support has been removed as it is deprecated. # cPanel no longer ships /scripts/easyapache and EA3 is not supported on # any current cPanel version, so EA3 build logic was removed in CLOS-3844. # The cloudlinux_ea3_to_ea4 script is still used for EA4 repository # configuration despite its legacy name. # See: https://cloudlinux.atlassian.net/browse/CLOS-3844 if [ "$PANEL" = "cpanel" ] ; then echo "Downloading the 'cloudlinux_ea3_to_ea4' script" pushd ~ > /dev/null || { echo "Failed to switch to homedir before downloading cloudlinux_ea3_to_ea4, exiting"; exit 1; } if [[ "$skip_ea4_script_download" == "false" ]]; then rm -f ./cloudlinux_ea3_to_ea4 wget "${PUBLIC_REPO_URL}/cloudlinux/sources/cloudlinux_ea3_to_ea4" 2>&1 | tee -a "${log}" fi if [ -f ./cloudlinux_ea3_to_ea4 ]; then cloudlinux_ea3_to_ea4_args=(--convert) if [[ "true" == "${test_updates}" ]]; then cloudlinux_ea3_to_ea4_args=("${cloudlinux_ea3_to_ea4_args[@]}" --beta) fi if [[ "true" == "${INSTALL_LOWER_VERSION}" ]]; then cloudlinux_ea3_to_ea4_args=("${cloudlinux_ea3_to_ea4_args[@]}" --allow-nobest) fi sh ./cloudlinux_ea3_to_ea4 "${cloudlinux_ea3_to_ea4_args[@]}" 2>&1 | tee -a "${log}" /scripts/restartsrv_httpd 2>&1 | tee -a "${log}" else echo "Failed to download cloudlinux_ea3_to_ea4. EasyApache4 setup for CloudLinux failed" 2>&1 | tee -a "${log}" fi popd > /dev/null || { echo "Failed to popd to previous directory, continuing as is"; } fi if [ "$PANEL" = "directadmin" ] && [ "$builddirectadmin" = "true" ]; then echo "Adding admin user to wheel group..." 2>&1 | tee -a "${log}" da_admin_user=$(/usr/bin/cldetect --print-da-admin) /usr/sbin/usermod -a -G wheel $da_admin_user 2>&1 | tee -a "${log}" echo "Apache build enabled, building..." 2>&1 | tee -a "${log}" if [ -f /usr/local/directadmin/custombuild/build ] ; then if [[ "${cl_solo_edition}" == "true" ]]; then echo "Solo edition detected, skipping DirectAdmin CloudLinux Apache build (mod_hostinglimits not needed)" 2>&1 | tee -a "${log}" else /usr/local/directadmin/custombuild/build set cloudlinux yes 2>&1 | tee -a "${log}" check_pipestatus 0 "Command failed, please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" da_webserver=$(grep '^webserver=' /usr/local/directadmin/custombuild/options.conf 2>/dev/null | cut -d= -f2) if [ "$da_webserver" = "litespeed" ] || [ "$da_webserver" = "openlitespeed" ]; then echo "DirectAdmin webserver is set to '${da_webserver}', skipping Apache build" 2>&1 | tee -a "${log}" else echo "Apache build enabled, building..." 2>&1 | tee -a "${log}" /usr/local/directadmin/custombuild/build apache check_pipestatus 0 "Apache build failed, the CloudLinux installation can't be continued. Please contact CloudLinux support (https://cloudlinux.zendesk.com/hc/requests/new) to check if the issue is related to cldeploy script." echo "Apache build succeeded" 2>&1 | tee -a "${log}" fi fi fi fi fi # ============================================================================= # MAIN EXECUTION FLOW - STEP 14C: Disable cPanel fork-bomb protection for CloudLinux # ============================================================================= # cPanel's fork-bomb protection conflicts with CloudLinux resource management (LVE). # When converting to CloudLinux, the cPanel UI option to manage fork-bomb protection # is removed, but if it was enabled before conversion, it remains active and cannot # be disabled through the UI anymore. if [[ "$PANEL" == "cpanel" ]]; then # Check for active fork-bomb protection files in /etc/profile.d/ if [[ -f /etc/profile.d/limits.csh ]] || \ [[ -f /etc/profile.d/limits.sh ]]; then echo "Disabling cPanel fork-bomb protection (incompatible with CloudLinux)..." | tee -a "${log}" if [[ -x /usr/local/cpanel/bin/install-login-profile ]]; then /usr/local/cpanel/bin/install-login-profile --uninstall limits 2>&1 | tee -a "${log}" echo "cPanel fork-bomb protection has been disabled" | tee -a "${log}" else echo "Warning: Could not find cPanel install-login-profile utility" | tee -a "${log}" echo "You may need to manually disable fork-bomb protection by running:" | tee -a "${log}" echo " /usr/local/cpanel/bin/install-login-profile --uninstall limits" | tee -a "${log}" fi fi fi # ============================================================================= # MAIN EXECUTION FLOW - STEP 14D: Notify cPanel of distribution change # ============================================================================= # After converting to CloudLinux, notify cPanel that the OS has changed so it # can update its internal OS detection cache. This ensures WHM correctly # displays "CloudLinux" instead of the original distribution (e.g., AlmaLinux). # While cPanel's cpanel-trigger-os-release package should handle this via RPM # triggers, explicitly calling the hook ensures the cache is refreshed even # if the trigger fails or fires at an unexpected time. # See: https://cloudlinux.atlassian.net/browse/CLOS-3850 if [[ "$PANEL" == "cpanel" ]]; then CPANEL_DISTRO_HOOK="/usr/local/cpanel/scripts/distro_changed_hook" if [[ -x "$CPANEL_DISTRO_HOOK" ]]; then echo "Notifying cPanel of distribution change..." | tee -a "${log}" "$CPANEL_DISTRO_HOOK" 2>&1 | tee -a "${log}" echo "cPanel OS cache has been refreshed" | tee -a "${log}" else echo "Warning: cPanel distro_changed_hook not found at $CPANEL_DISTRO_HOOK" | tee -a "${log}" echo "You may need to manually refresh the OS cache by removing /var/cpanel/caches/Cpanel-OS" | tee -a "${log}" echo "and then running: /usr/local/cpanel/bin/build_global_cache" | tee -a "${log}" fi fi # ============================================================================= # MAIN EXECUTION FLOW - STEP 15: Post-conversion configuration # ============================================================================= add_digitalocean_kexec if [ "$LINODE" = "true" ]; then write_linode_grub_conf echo "Please edit your Linode profile, select pv-grub-x86_64 or pv-grub-x86_32 as a boot kernel and uncheck \"Xenify Distro\" button" fi if [ "$OS_VERSION" = "7" ] && [ "$LINODE_KVM" = "true" ]; then echo "Please edit configuration of your Linode and select \"GRUB 2\" in Boot Settings - Kernel" fi if [ "$OS_VERSION" = "6" ] && [ "$LINODE_KVM" = "true" ]; then echo "Please edit configuration of your Linode and select \"GRUB\" in Boot Settings - Kernel" fi if [ "$LES" = "true" ]; then echo "Linux Environment Security was disabled, you can re-enable it if needed" fi # CentOS 7 OVH grub.conf if [ -f /etc/grub.d/06_OVHkernel ] && compgen -G "/boot/bzImage*" > /dev/null ; then mv /boot/bzImage* /etc/cl-convert-saved/ grub2-mkconfig -o /boot/grub2/grub.cfg if [ -e /sys/firmware/efi ]; then # Hardening to make sure that on EFI we update correct grub.cfg even # if it's in other location [[ -e /etc/grub2-efi.cfg ]] && grub2-mkconfig -o /etc/grub2-efi.cfg || echo "Your EFI-based system doesn't have correct symlink \"/etc/grub2-efi.cfg\" this may cause boot troubles. Please, fix it to point to your current grub.cfg file and run grub2-mkconfig -o /etc/grub2-efi.cfg" | tee -a /var/log/ovh-cl-deploy.log fi echo "Your OVH server is now configured to boot into the CloudLinux kernel from local HDD" | tee -a /var/log/ovh-cl-deploy.log echo "OVH kernel was saved to /etc/cl-convert-saved/" | tee -a /var/log/ovh-cl-deploy.log echo "In case of troubles please boot from network, copy $(ls /etc/cl-convert-saved/bzImage*) to /boot and run" | tee -a /var/log/ovh-cl-deploy.log echo "grub2-mkconfig -o /boot/grub2/grub.cfg" | tee -a /var/log/ovh-cl-deploy.log echo "You can find a copy of this message in /var/log/ovh-cl-deploy.log" | tee -a "${log}" fi convert_cl7_to_cl7h_if_needed if [[ "${cl_container}" != "true" ]]; then check_validity_of_default_grub_record fi if [ "$PANEL" = "" ] ; then packages_to_reinstall="lvemanager lve-utils alt-python27-cllib" supported_panels="cPanel" if [[ "${cl_solo_edition}" == "true" ]]; then packages_to_reinstall="${packages_to_reinstall} lvemanager-xray" else supported_panels="${supported_panels}, DirectAdmin, Plesk" packages_to_reinstall="${packages_to_reinstall} cagefs" fi echo "Warning!! If you will install a control panel natively supported by CloudLinux (${supported_panels}) later," echo "then you MUST reinstall the CloudLinux Manager packages with the following command:" echo "yum reinstall -y ${packages_to_reinstall}" echo "" fi # run rhn_check again in order to trigger post-registration hooks # usually it is executed right at the time of registration, # but cldeploy is special case where registration happens # on machine where cloudlinux packages are not installed yet if [[ "$OS_VERSION" -ge "8" ]]; then echo "Final reconfiguration of CloudLinux edition specific features" if [[ "$registration" == "true" ]]; then rhn_check --allow-transition | tee -a "${log}" else echo "Skipping rhn_check because registration was skipped" | tee -a "${log}" fi else # cl6 and cl7 are eol, we keep this check here # only to update user-edition file if [[ "$registration" == "true" ]]; then rhn_check | tee -a "${log}" else echo "Skipping rhn_check because registration was skipped" | tee -a "${log}" fi fi # install alt_els only after cloudlinux packages are installed and the server is # registered: rhn_check provides the els JWT auth vars during registration, so # skip this when registration was skipped (no auth vars, repos 401). if [[ "$OS_VERSION" -ge "7" && "$registration" == "true" ]]; then install_alt_els_repositories check_pipestatus 0 "Unable to set up PHP/NodeJS/Python/Ruby auxiliary repositories, please contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new" fi # ============================================================================= # MAIN EXECUTION FLOW - STEP 16: Final boot configuration # ============================================================================= check_and_fix_grub_efi_cfg check_and_fix_grub_settings if [[ "$BLSCFG_CHANGED" == "true" ]]; then echo "WARNING! GRUB_ENABLE_BLSCFG was set to true in grub config to load the CL kernel after reboot." | tee -a "${log}" echo "This option is enabled by default in RHEL-based distributives with version higher than 8." | tee -a "${log}" echo "It causes the grub menu to be generated dynamically, using configs from /boot/loader/entries." | tee -a "${log}" echo "If you have custom grub settings, please ensure they were not overridden, or reapply them via grubby" | tee -a "${log}" echo "For details, please check the following article https://fedoraproject.org/wiki/Changes/BootLoaderSpecByDefault" | tee -a "${log}" show_reboot_message=false fi # ============================================================================= # MAIN EXECUTION FLOW - STEP 17: Final cleanup and completion # ============================================================================= check_update_uefi_boot_entries # CL10 IBT safety: re-enable kmod-lve autoload now that conversion succeeded and the # CloudLinux tuned profile (ibt=off) is active. The module loads on the next reboot. restore_kmodlve_autoload [[ "$show_reboot_message" == "true" ]] && echo "Please reboot the server to apply the changes" | tee -a "${log}" echo "You can find complete log in /var/log/cldeploy.log" if [[ "$OS_VERSION" -ge "8" ]]; then rm -f /etc/yum.repos.d/"${BASE_REPO}.repo" &>/dev/null # Double-check whether we have any cldeploy-related repos left if compgen -G "/etc/yum.repos.d/repo.cloudlinux.com_cloudlinux*" >/dev/null; then # If there are, remove them too rm -f /etc/yum.repos.d/repo.cloudlinux.com_cloudlinux* &>/dev/null fi fi [[ -f /usr/bin/systemctl ]] && /usr/bin/systemctl daemon-reload &> /dev/null check_boot_duplicates rm -f $lock exit 0