Pre-requisites check script
Published 30 January 2023
You can check your machine against the Redgate Clone pre-requisites by running the following command:
curl -sSL https://rd.gt/3RL6ioU | sudo bash
To run the script manually:
- Copy the contents of the script below and save it to the file
pre-requisite-check.sh - Ensure that the script is executable and if not run
chmod +x ./pre-requisite-check.sh - The script requires superuser permissions so will need to be executed with sudo, i.e.
sudo ./pre-requisite-check.sh
#!/usr/bin/env bash
#############################################################################################################################
# Name : prerequisite-check.sh
# Description : Checks a Linux machine against the Redgate Clone prerequisites and requirements
# i.e. the items listed here https://documentation.red-gate.com/x/nANsC
#############################################################################################################################
###################################################### Requirements #########################################################
expected_os_name_ubuntu="ubuntu"
expected_os_name_rhel="red hat enterprise linux"
minimum_os_version_ubuntu="22.04"
minimum_os_version_rhel="8.0"
minimum_cpu_count=8
minimum_ram_size_in_gib=16
expected_system_disk_partition_table_type="gpt"
minimum_system_disk_size_human_readable="80Gi"
minimum_data_disk_size_human_readable="100Gi"
minimum_root_size_human_readable="2Gi"
minimum_home_size_human_readable="4Gi"
minimum_tmp_size_human_readable="3Gi"
minimum_var_size_human_readable="50Gi"
minimum_usr_size_human_readable="8Gi"
###################################################### Script setup #########################################################
set -Eeuo pipefail
if [[ $(uname | tr '[:upper:]' '[:lower:]') != "linux" ]]; then
echo "This script can only be run on a Linux environment, but environment type $(uname) was detected."
exit 1
fi
if [[ $(/usr/bin/id -u) -ne 0 ]]; then
echo "This script requires root permissions. Please rerun using sudo."
exit 1
fi
errors=()
function report_and_exit() {
echo
if [ ${#errors[@]} != 0 ]; then
echo "Found the following errors..."
for error in "${errors[@]}"; do
echo " • $error"
done
exit 1
else
echo "No errors were found!"
exit 0
fi
}
section_start_error_count=0
function start_section() {
section_start_error_count=${#errors[@]}
printf " Checking %s requirements... " "$1"
}
function end_section() {
if [[ $section_start_error_count -eq ${#errors[@]} ]]; then
echo "OK"
else
echo "FAIL"
fi
}
echo "Checking Redgate Clone host VM pre-requisites (https://documentation.red-gate.com/x/kgARCQ)..."
####################################################### OS checks ###########################################################
start_section "OS"
if ls /etc/*-release 1> /dev/null 2>&1; then
os_name=$(cat /etc/*-release | grep "^NAME=" | cut -d'"' -f2 | tr '[:upper:]' '[:lower:]')
os_version=$(cat /etc/*-release | grep "^VERSION_ID=" | cut -d= -f2 | xargs)
if [ "$os_name" == "$expected_os_name_ubuntu" ] || [ "$os_name" == "$expected_os_name_rhel" ]; then
if [[ -z "${os_version// }" ]]; then
errors+=("The $os_name version could not be detected. Redgate Clone requires at least version $minimum_os_version.")
else
is_rhel8=
if [ "$os_name" == "$expected_os_name_ubuntu" ]; then
minimum_os_version=$minimum_os_version_ubuntu
else
minimum_os_version=$minimum_os_version_rhel
major_version=$(printf %.1s "$os_version")
if [ "$major_version" == "8" ]; then
is_rhel8=true
fi
fi
if [[ $(printf "%s\n%s" "$minimum_os_version" "$os_version" | sort -V | head -n1) != "$minimum_os_version" ]]; then
errors+=("The $os_name version must be at least $minimum_os_version but was detected to be $os_version.")
fi
fi
else
errors+=("The operating system must be $expected_os_name_rhel or $expected_os_name_ubuntu but it was detected to be $os_name.")
end_section
report_and_exit # Exit early as the other checks may not work as expected.
fi
else
errors+=("The operating system must be $expected_os_name_rhel or $expected_os_name_ubuntu but the distribution could not be detected. The uname command returns \"$(uname -a)\".")
end_section
report_and_exit # Exit early as the other checks may not work as expected.
fi
end_section
#################################################### Hardware checks ########################################################
start_section "CPU"
cpu_count=$(nproc --all)
if [ "$cpu_count" -lt "$minimum_cpu_count" ]
then
errors+=("Redgate Clone requires a minimum of $minimum_cpu_count vCPUs, but $cpu_count were detected.")
fi
end_section
start_section "RAM"
if [[ $(which dmidecode) ]]; then
ram_size_in_gib=$(dmidecode -t memory | grep "^[[:space:]]Size:" | cut -d: -f2 | tr -d ' B' | grep -v -x -F "NoModuleInstalled" | numfmt --from=iec | awk 'BEGIN {count=0;} {count+=$1;} END {print count/1073741824;}')
if [ "$ram_size_in_gib" -lt "$minimum_ram_size_in_gib" ]
then
errors+=("Redgate Clone requires a minimum of ${minimum_ram_size_in_gib}Gi RAM, but ${ram_size_in_gib}Gi was detected.")
fi
else
errors+=("The amount of RAM could not be detected because the dmidecode utility is missing. Redgate Clone requires a minimum of ${minimum_ram_size_in_gib}Gi RAM.")
fi
end_section
###################################################### Disk checks ##########################################################
start_section "storage"
minimum_system_disk_size=$(numfmt --from=auto $minimum_system_disk_size_human_readable)
minimum_data_disk_size=$(numfmt --from=auto $minimum_data_disk_size_human_readable)
system_disk=$(lsblk --bytes --output NAME,MOUNTPOINT,PKNAME --list --paths | awk '{if($2=="/")print $3}')
system_disk_size=$(lsblk --bytes --output NAME,SIZE --list --paths | awk '{if($1=="'"$system_disk"'")print $2}')
if [ "$is_rhel8" = true ]; then
system_partition_table_type=$(sudo fdisk -l 2> /dev/null | awk '/Disklabel type:/ {print $3}')
else
system_partition_table_type=$(lsblk --output NAME,PTTYPE --list --paths | awk '{if($1=="'"$system_disk"'")print $2}')
fi
if [ "$((system_disk_size))" -lt "$((minimum_system_disk_size))" ]; then
system_disk_size_human_readable=$(numfmt --to=iec-i "$system_disk_size")
errors+=("The system disk needs to be at least $minimum_system_disk_size_human_readable in size. Disk $system_disk was detected to be the system disk but its size is only $system_disk_size_human_readable.")
fi
if [ "$system_partition_table_type" != "$expected_system_disk_partition_table_type" ]; then
errors+=("The system disk's partition table type must be $expected_system_disk_partition_table_type but was detected to be $system_partition_table_type.")
fi
if [ "$is_rhel8" = true ]; then
possible_data_disks=$(lsblk --bytes --output NAME,SIZE,TYPE | awk '($2 >= '"$minimum_data_disk_size"' && $3 == "disk") {print "/dev/"$1;}' | tr ' ' '\n')
else
possible_data_disks=$(lsblk --bytes --output NAME,SIZE,TYPE,PATH | awk '($2 >= '"$minimum_data_disk_size"' && $3 == "disk") {print $4;}' | tr ' ' '\n')
fi
data_disks=()
declare -A filesystems
for blockdevice in $possible_data_disks; do
filesystem_count=$(lsblk --noheadings --fs --output NAME,FSTYPE --list "$blockdevice" | awk 'BEGIN {count=0;} {if ($2) count+=1} END {print count;}')
if [ "$filesystem_count" -eq 0 ]
then
data_disks+=("$blockdevice")
else
filesystems[$blockdevice]=$filesystem_count
fi
done
if [ ${#data_disks[@]} == 0 ]; then
filesystem_list=""
for key in "${!filesystems[@]}"; do
filesystem_list+=" Device $key is large enough but already has ${filesystems[$key]} existing filesystems."
done
errors+=("No disks were detected that have a size greater than $minimum_data_disk_size_human_readable and have no existing filesystems.$filesystem_list")
fi
# check if they are using LVM volumes and if so if there is enough space assigned to the root, home, tmp, var and usr directories
if command -v lvs &> /dev/null
then
if [ -n "$(lvs)" ]; then
root_lv=$(lsblk --output NAME,MOUNTPOINT --list --paths | awk '{if($2=="/")print $1}')
home_lv=$(lsblk --output NAME,MOUNTPOINT --list --paths | awk '{if($2=="/home")print $1}')
tmp_lv=$(lsblk --output NAME,MOUNTPOINT --list --paths | awk '{if($2=="/tmp")print $1}')
var_lv=$(lsblk --output NAME,MOUNTPOINT --list --paths | awk '{if($2=="/var")print $1}')
usr_lv=$(lsblk --output NAME,MOUNTPOINT --list --paths | awk '{if($2=="/usr")print $1}')
check_lv() {
lv=$1
minimum_size=$2
directory=$3
if [[ $lv == *"/dev/mapper"* ]]; then
lv_size=$(lsblk --bytes --output NAME,SIZE --list --paths | awk '{if($1=="'"$lv"'")print $2}')
if [ "$((lv_size))" -lt "$((minimum_size))" ]; then
lv_size_human_readable=$(numfmt --to=iec-i "$lv_size")
errors+=("The $directory directory needs to be at least $(numfmt --to=iec-i "$minimum_size") in size. Logical volume $lv was detected to be the $directory directory but its size is only $lv_size_human_readable.")
fi
else
errors+=("The $directory directory is not on an LVM.")
fi
}
minimum_root_size=$(numfmt --from=auto $minimum_root_size_human_readable)
minimum_home_size=$(numfmt --from=auto $minimum_home_size_human_readable)
minimum_tmp_size=$(numfmt --from=auto $minimum_tmp_size_human_readable)
minimum_usr_size=$(numfmt --from=auto $minimum_usr_size_human_readable)
minimum_var_size=$(numfmt --from=auto $minimum_var_size_human_readable)
check_lv "$root_lv" "$minimum_root_size" "/"
check_lv "$home_lv" "$minimum_home_size" "/home"
check_lv "$tmp_lv" "$minimum_tmp_size" "/tmp"
check_lv "$var_lv" "$minimum_var_size" "/var"
check_lv "$usr_lv" "$minimum_usr_size" "/usr"
fi
fi
end_section
################################################# Internet connectivity #####################################################
start_section "Internet connectivity"
set +e
if ! curl --silent --head --retry 3 --output /dev/null http://www.google.com/; then
errors+=("Internet connectivity was not detected.")
fi
set -e
end_section
################################################# Installation script availability #####################################################
start_section "Installation script availability"
readonly INSTALLATION_TEST_URL=https://k8s.kurl.sh/cloning-capability-app
set +e
if ! curl --silent --head --retry 3 --output /dev/null $INSTALLATION_TEST_URL; then
errors+=("Unable to reach the URL hosting the installation script: $INSTALLATION_TEST_URL.")
fi
set -e
end_section
################################################ Kernel configuration values ####################################################
start_section "Kernel configuration"
max_user_instances=$(sysctl fs.inotify.max_user_instances | awk '{print $NF}')
if [ "$max_user_instances" -lt 512 ]
then
errors+=("The kernel configuration fs.inotify.max_user_instances should be set to at least 512 but was detected to be $max_user_instances.")
fi
max_io_request=$(sysctl fs.aio-max-nr | awk '{print $NF}')
if [ "$max_io_request" -lt 1048576 ]
then
errors+=("The kernel configuration fs.aio-max-nr should be set to at least 1048576 but was detected to be $max_io_request.")
fi
end_section
################################################ Report findings to user ####################################################
report_and_exit