From e5ca4bb449befdd3cc842e3f4193314614de8817 Mon Sep 17 00:00:00 2001 From: 007revad <39733752+007revad@users.noreply.github.com> Date: Fri, 17 Mar 2023 19:25:59 +1100 Subject: [PATCH] Update syno_hdd_db.sh v1.1.15 - Added support for M.2 drives on a PCI card (M2Dxx and E10G18-T1 and future models). - Improved flags/options checking and added usage help. - Can now download the latest script version for you (if you have user home service enabled in DSM). - Now adds 'support_m2_pool="yes"' line for models that don't have support_m2_pool in synoinfo.conf - To (hopefully) prevent losing your SSH created M2 volume when running this script on models that DSM 7.2 Beta does not list as supported for creating M2 volumes. - Changed Synology model detection to be more reliable (for models that came in different variations). - Changed checking drive_db_test_url setting to be more durable. --- syno_hdd_db.sh | 547 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 384 insertions(+), 163 deletions(-) diff --git a/syno_hdd_db.sh b/syno_hdd_db.sh index 61d0052..a17b6b2 100644 --- a/syno_hdd_db.sh +++ b/syno_hdd_db.sh @@ -23,17 +23,32 @@ #-------------------------------------------------------------------------------------------------- # TODO +# Bypass M.2 volume lock for unsupported M.2 drives. +# # Detect if expansion unit(s) connected and get model(s) and edit expansion unit db files. # Or add support for specifying user's expansion unit model(s) as arguments. # Or maybe use the shotgun approach and update all expansion unit db files. # -# Add support for M.2 SATA and NVMe drives on a M2D17 PCI card. -# -# Maybe also edit the other disk compatibility DB in synoboot, used during boot time. +# Maybe also edit the other disk compatibility db in synoboot, used during boot time. # It's also parsed and checked and probably in some cases it could be more critical to patch that one instead. # DONE -# Added check that M.2 volume support is enabled. +# Added support for M.2 drives on a PCI card (M2Dxx and E10G18-T1 and future models). +# +# Improved flags/options checking and added usage help. +# +# Can now download the latest script version for you (if you have user home service enabled in DSM). +# +# Now adds 'support_m2_pool="yes"' line for models that don't have support_m2_pool in synoinfo.conf +# to (hopefully) prevent losing your SSH created M2 volume when running this script on models +# that DSM 7.2 Beta does not list as supported for creating M2 volumes. +# +# Changed Synology model detection to be more reliable (for models that came in different variations). +# +# Changed checking drive_db_test_url setting to be more durable. +# +# +# Added check that M.2 volume support is enabled (on supported models). # # Added support for M.2 SATA drives. # @@ -63,58 +78,100 @@ # Optionally disable "support_disk_compatibility". -scriptver="v1.1.14" +scriptver="v1.1.15" +script=Synology_HDD_db +repo="007revad/Synology_HDD_db" -# Check latest release with GitHub API -get_latest_release() { - curl --silent "https://api.github.com/repos/$1/releases/latest" | - grep '"tag_name":' | # Get tag line - sed -E 's/.*"([^"]+)".*/\1/' # Pluck JSON value + +# Shell Colors +#Black='\e[0;30m' +Red='\e[0;31m' +#Green='\e[0;32m' +Yellow='\e[0;33m' +#Blue='\e[0;34m' +#Purple='\e[0;35m' +Cyan='\e[0;36m' +#White='\e[0;37m' +Error='\e[41m' +Off='\e[0m' + + +usage(){ + cat < /dev/null ; then - echo -e "\e[0;36mThere is a newer version of this script available.\e[0m" - echo -e "Current version: ${scriptver}\nLatest version: $tag" - echo "https://github.com/007revad/Synology_HDD_db/releases/latest" - echo "" - sleep 10 -fi +scriptversion(){ + cat < /dev/null ; then + echo -e "${Cyan}There is a newer version of this script available.${Off}" + echo -e "Current version: ${scriptver}\nLatest version: $tag" + if [[ ! -d $HOME ]]; then + # Can't download to home + echo "https://github.com/$repo/releases/latest" + sleep 10 + elif [[ -f $HOME/$script-$shorttag.tar.gz ]]; then + # Latest version tar.gz in home but they're using older version + echo "https://github.com/$repo/releases/latest" + sleep 10 + else + echo -e "${Cyan}Do you want to download $tag now?${Off} {y/n]" + read -r -t 30 reply + if [[ ${reply,,} == "y" ]]; then + if ! curl -LJO "https://github.com/$repo/archive/refs/tags/$tag.tar.gz"; then + echo -e "${Error}ERROR ${Off} Failed to download $script-$shorttag.tar.gz!" + else + if [[ -f $HOME/$script-$shorttag.tar.gz ]]; then + if ! tar -xf "$HOME/$script-$shorttag.tar.gz"; then + echo -e "${Error}ERROR ${Off} Failed to extract $script-$shorttag.tar.gz!" + else + if ! rm "$HOME/$script-$shorttag.tar.gz"; then + echo -e "${Error}ERROR ${Off} Failed to delete downloaded $script-$shorttag.tar.gz!" + else + echo -e "\n$tag and changes.txt are in ${Cyan}$shorthome/$script-$shorttag${Off}" + echo -e "${Cyan}Do you want to stop this script so you can run the new one?${Off} {y/n]" + read -r -t 30 reply + if [[ ${reply,,} == "y" ]]; then exit; fi + fi + fi + else + echo -e "${Error}ERROR ${Off} $shorthome/$script-$shorttag.tar.gz not found!" + #ls $HOME/ | grep "$script" # debug + fi + fi + fi + fi fi #------------------------------------------------------------------------------ # Get list of installed SATA, SAS and M.2 NVMe/SATA drives +getdriveinfo() { + # Get drive model and firmware version + hdmodel=$(cat "$1/device/model") + hdmodel=$(printf "%s" "$hdmodel" | xargs) # trim leading and trailing white space + + fwrev=$(cat "$1/device/rev") + fwrev=$(printf "%s" "$fwrev" | xargs) # trim leading and trailing white space + + if [[ $hdmodel ]] && [[ $fwrev ]]; then + hdlist+=("${hdmodel},${fwrev}") + fi +} + +getm2info() { + nvmemodel=$(cat "$1/device/model") + nvmemodel=$(printf "%s" "$nvmemodel" | xargs) # trim leading and trailing white space + if [[ $2 == "nvme" ]]; then + nvmefw=$(cat "$1/device/firmware_rev") + elif [[ $2 == "nvc" ]]; then + nvmefw=$(cat "$1/device/rev") + fi + nvmefw=$(printf "%s" "$nvmefw" | xargs) # trim leading and trailing white space + + if [[ $nvmemodel ]] && [[ $nvmefw ]]; then + nvmelist+=("${nvmemodel},${nvmefw}") + fi +} + +getcardmodel() { + # Get M.2 card model + cardmodel=$(synodisk --m2-card-model-get "$1") + if [[ $cardmodel =~ M2D[0-9][0-9] ]]; then + # M2 adaptor card + m2carddblist+=("${model}_${cardmodel,,}${version}.db") # M.2 card's db file + m2cardlist+=("$cardmodel") # M.2 card + elif [[ $cardmodel =~ E[0-9][0-9]+M.+ ]]; then + # Ethernet + M2 adaptor card + m2carddblist+=("${model}_${cardmodel,,}${version}.db") # M.2 card's db file + m2cardlist+=("$cardmodel") # M.2 card + fi +} + + for d in /sys/block/*; do - #echo $d # debug case "$(basename -- "${d}")" in sd*|hd*) - if [[ $d =~ [hs]d[a-z]$ ]]; then - hdmodel=$(cat "$d/device/model") - hdmodel=$(printf "%s" "$hdmodel" | xargs) # trim leading and trailing white space - #echo "Model: '$hdmodel'" # debug - - fwrev=$(cat "$d/device/rev") - fwrev=$(printf "%s" "$fwrev" | xargs) # trim leading and trailing white space - #echo "Firmware: '$fwrev'" # debug - - if [[ $hdmodel ]] && [[ $fwrev ]]; then - hdlist+=("${hdmodel},${fwrev}") - fi + if [[ $d =~ [hs]d[a-z][a-z]?$ ]]; then + # Get drive model and firmware version + getdriveinfo "$d" fi ;; sata*|sas*) if [[ $d =~ (sas|sata)[0-9][0-9]?[0-9]?$ ]]; then - hdmodel=$(cat "$d/device/model") - hdmodel=$(printf "%s" "$hdmodel" | xargs) # trim leading and trailing white space - #echo "Model: '$hdmodel'" # debug - - fwrev=$(cat "$d/device/rev") - fwrev=$(printf "%s" "$fwrev" | xargs) # trim leading and trailing white space - #echo "Firmware: '$fwrev'" # debug - - if [[ $hdmodel ]] && [[ $fwrev ]]; then - hdlist+=("${hdmodel},${fwrev}") - fi + # Get drive model and firmware version + getdriveinfo "$d" fi ;; nvme*) if [[ $d =~ nvme[0-9][0-9]?n[0-9][0-9]?$ ]]; then if [[ $m2 != "no" ]]; then - nvmemodel=$(cat "$d/device/model") - nvmemodel=$(printf "%s" "$nvmemodel" | xargs) # trim leading and trailing white space - #echo "NVMe Model: '$nvmemodel'" # debug - - nvmefw=$(cat "$d/device/firmware_rev") - nvmefw=$(printf "%s" "$nvmefw" | xargs) # trim leading and trailing white space - #echo "NVMe Firmware: '$nvmefw'" # debug - - if [[ $nvmemodel ]] && [[ $nvmefw ]]; then - nvmelist+=("${nvmemodel},${nvmefw}") - fi + getm2info "$d" "nvme" + # Get M.2 card model if in M.2 card + getcardmodel "/dev/$d" fi fi ;; @@ -187,18 +332,9 @@ for d in /sys/block/*; do #if [[ $d =~ nvc[0-9][0-9]?p[0-9][0-9]?$ ]]; then if [[ $d =~ nvc[0-9][0-9]?$ ]]; then if [[ $m2 != "no" ]]; then - nvmemodel=$(cat "$d/device/model") - nvmemodel=$(printf "%s" "$nvmemodel" | xargs) # trim leading and trailing white space - #echo "M.2 SATA Model: '$nvmemodel'" # debug - - #nvmefw=$(cat "$d/device/firmware_rev") - nvmefw=$(cat "$d/device/rev") - nvmefw=$(printf "%s" "$nvmefw" | xargs) # trim leading and trailing white space - #echo "M.2 SATA Firmware: '$nvmefw'" # debug - - if [[ $nvmemodel ]] && [[ $nvmefw ]]; then - nvmelist+=("${nvmemodel},${nvmefw}") - fi + getm2info "$d" "nvc" + # Get M.2 card model if in M.2 card + getcardmodel "/dev/$d" fi fi ;; @@ -206,16 +342,25 @@ for d in /sys/block/*; do done +sortarray(){ + # Sort $1 array into new $2 array to remove duplicates + local -n inarray=$1 + outarray=() + if [[ ${#inarray[@]} -gt "0" ]]; then + while IFS= read -r -d '' x; do + outarray+=("$x") + done < <(printf "%s\0" "${inarray[@]}" | sort -uz) + fi +} + + # Sort hdlist array into new hdds array to remove duplicates -if [[ ${#hdlist[@]} -gt "0" ]]; then - while IFS= read -r -d '' x; do - hdds+=("$x") - done < <(printf "%s\0" "${hdlist[@]}" | sort -uz) -fi +sortarray "hdlist" +hdds=${outarray[*]} # Check hdds array isn't empty if [[ ${#hdds[@]} -eq "0" ]]; then - echo -e "\e[41mERROR\e[0m No drives found!" && exit 2 + echo -e "${Error}ERROR${Off} No drives found!" && exit 2 else echo "HDD/SSD models found: ${#hdds[@]}" num="0" @@ -228,11 +373,8 @@ fi # Sort nvmelist array into new nvmes array to remove duplicates -if [[ ${#nvmelist[@]} -gt "0" ]]; then - while IFS= read -r -d '' x; do - nvmes+=("$x") - done < <(printf "%s\0" "${nvmelist[@]}" | sort -uz) -fi +sortarray "nvmelist" +nvmes=${outarray[*]} # Check nvmes array isn't empty if [[ ${#nvmes[@]} -eq "0" ]]; then @@ -250,14 +392,40 @@ else fi +# M.2 card db files +# Sort m2carddblist array into new m2carddbs array to remove duplicates +sortarray "m2carddblist" +m2carddbs=${outarray[*]} + +# M.2 cards +# Sort m2cardlist array into new m2cards array to remove duplicates +sortarray "m2cardlist" +m2cards=${outarray[*]} + +# Check m2cards array isn't empty +if [[ ${#m2cards[@]} -gt "0" ]]; then + echo "M.2 card models found: ${#m2cards[@]}" + num="0" + while [[ $num -lt "${#m2cards[@]}" ]]; do + echo "${m2cards[num]}" + num=$((num +1)) + done + echo +fi + + #------------------------------------------------------------------------------ -# Check database and add our drives if needed +# Check databases and add our drives if needed db1="/var/lib/disk-compatibility/${model}_host${version}.db" db2="/var/lib/disk-compatibility/${model}_host${version}.db.new" +dbpath="/var/lib/disk-compatibility/" -if [[ ! -f "$db1" ]]; then echo -e "\e[41mERROR\e[0m $db1 not found!" && exit 3; fi -#if [[ ! -f "$db2" ]]; then echo -e "\e[41mERROR\e[0m $db2 not found!" && exit 4; fi +synoinfo="/etc.defaults/synoinfo.conf" + + +if [[ ! -f "$db1" ]]; then echo -e "${Error}ERROR 3${Off} $db1 not found!" && exit 3; fi +#if [[ ! -f "$db2" ]]; then echo -e "${Error}ERROR 4${Off} $db2 not found!" && exit 4; fi # new installs don't have a .db.new file @@ -269,30 +437,36 @@ elif grep -F '{"success":1,"list":[' "$db1" >/dev/null; then # DSM 6 drive db files start with {"success":1,"list":[ dbtype=6 else - echo -e "\e[41mERROR\e[0m Unknown database type $(basename -- "${db1}")!" + echo -e "${Error}ERROR${Off} Unknown database type $(basename -- "${db1}")!" exit 7 fi #echo "dbtype: $dbtype" # debug -# Backup database file if needed -if [[ ! -f "$db1.bak" ]]; then - if cp "$db1" "$db1.bak"; then - echo -e "Backed up database to $(basename -- "${db1}").bak\n" - else - echo -e "\e[41mERROR\e[0m Failed to backup $(basename -- "${db1}")!" - exit 5 +backupdb() { + # Backup database file if needed + if [[ ! -f "$1.bak" ]]; then + if cp "$1" "$1.bak"; then + echo -e "\nBacked up $(basename -- "${1}") database.\n" + else + echo -e "${Error}ERROR 5${Off} Failed to backup $(basename -- "${1}")!" + return 1 + fi fi -fi +} -# Shell Colors -Yellow='\e[0;33m' -Cyan='\e[0;36m' -Red='\e[0;31m' -Off=$'\e[0m' +# Backup host database file if needed +backupdb "$db1" || exit 5 + +# Backup synoinfo.conf if needed +backupdb "$synoinfo" || exit 9 + + +#------------------------------------------------------------------------------ +# Edit db files -function updatedb() { +updatedb() { hdmodel=$(printf "%s" "$1" | cut -d"," -f 1) fwrev=$(printf "%s" "$1" | cut -d"," -f 2) @@ -317,13 +491,16 @@ function updatedb() { #if sed -i "s/}}}/}},\"$hdmodel\":{$fwstrng$default/" "$2"; then # Don't need to add firmware version? if sed -i "s/}}}/}},\"$hdmodel\":{$default/" "$2"; then echo -e "Added ${Yellow}$hdmodel${Off} to ${Cyan}$(basename -- "$2")${Off}" + + # Count drives added to host db files if [[ $2 == "$db1" ]]; then db1Edits=$((db1Edits +1)) elif [[ $2 == "$db2" ]]; then db2Edits=$((db2Edits +1)) fi + else - echo -e "\n\e[41mERROR\e[0m Failed to update v7 $(basename -- "$2")${Off}" + echo -e "\n${Error}ERROR 6${Off} Failed to update v7 $(basename -- "$2")${Off}" exit 6 fi else @@ -343,13 +520,16 @@ function updatedb() { # {"success":1,"list":[{"model":"WD60EFRX-68MYMN1","firmware":"82.00A82","rec_intvl":[1]}, if sed -ir "s/$startstring/$startstring$string/" "$2"; then echo -e "Added ${Yellow}$hdmodel${Off} to ${Cyan}$(basename -- "$2")${Off}" + + # Count drives added to host db files if [[ $2 == "$db1" ]]; then db1Edits=$((db1Edits +1)) elif [[ $2 == "$db2" ]]; then db2Edits=$((db2Edits +1)) fi + else - echo -e "\n\e[41mERROR\e[0m Failed to update $(basename -- "$2")${Off}" + echo -e "\n${Error}ERROR 8${Off} Failed to update $(basename -- "$2")${Off}" exit 8 fi fi @@ -373,18 +553,36 @@ while [[ $num -lt "${#nvmes[@]}" ]]; do if [[ -f "$db2" ]]; then updatedb "${nvmes[$num]}" "$db2" fi + + #------------------------------------------------ + # M.2 adaptor cards + num2="0" + while [[ $num2 -lt "${#m2carddbs[@]}" ]]; do + if [[ -f "${dbpath}${m2carddbs[$num2]}" ]];then + backupdb "${dbpath}${m2carddbs[$num2]}" &&\ + updatedb "${nvmes[$num]}" "${dbpath}${m2carddbs[$num2]}" + else + echo -e "${Error}ERROR 10${Off} ${m2carddbs[$num2]} not found!" + fi + num2=$((num2 +1)) + done + #------------------------------------------------ + num=$((num +1)) done +#------------------------------------------------------------------------------ +# Edit /etc.defaults/synoinfo.conf + # Optionally disable "support_disk_compatibility" sdc=support_disk_compatibility -setting="$(get_key_value /etc.defaults/synoinfo.conf $sdc)" +setting="$(get_key_value $synoinfo $sdc)" if [[ $force == "yes" ]]; then if [[ $setting == "yes" ]]; then # Disable support_disk_compatibility - sed -i "s/${sdc}=\"yes\"/${sdc}=\"no\"/" "/etc.defaults/synoinfo.conf" - setting="$(get_key_value /etc.defaults/synoinfo.conf $sdc)" + sed -i "s/${sdc}=\"yes\"/${sdc}=\"no\"/" "$synoinfo" + setting="$(get_key_value "$synoinfo" $sdc)" if [[ $setting == "no" ]]; then echo -e "\nDisabled support disk compatibility." fi @@ -392,8 +590,8 @@ if [[ $force == "yes" ]]; then else if [[ $setting == "no" ]]; then # Enable support_disk_compatibility - sed -i "s/${sdc}=\"no\"/${sdc}=\"yes\"/" "/etc.defaults/synoinfo.conf" - setting="$(get_key_value /etc.defaults/synoinfo.conf $sdc)" + sed -i "s/${sdc}=\"no\"/${sdc}=\"yes\"/" "$synoinfo" + setting="$(get_key_value "$synoinfo" $sdc)" if [[ $setting == "yes" ]]; then echo -e "\nRe-enabled support disk compatibility." fi @@ -403,53 +601,76 @@ fi # Check m2 volume support enabled smp=support_m2_pool -setting="$(get_key_value /etc.defaults/synoinfo.conf ${smp})" -if [[ $setting == "no" ]]; then - sed -i "s/${smp}=\"no\"/${smp}=\"yes\"/" "/etc.defaults/synoinfo.conf" - setting="$(get_key_value /etc.defaults/synoinfo.conf ${smp})" +setting="$(get_key_value $synoinfo ${smp})" +enabled="" +if [[ ! $setting ]]; then + # Add support_m2_pool"yes" + echo 'support_m2_pool="yes"' >> "$synoinfo" + enabled="yes" +elif [[ $setting == "no" ]]; then + # Change support_m2_pool"no" to "yes" + sed -i "s/${smp}=\"no\"/${smp}=\"yes\"/" "$synoinfo" + enabled="yes" +elif [[ $setting == "yes" ]]; then + echo -e "\nM.2 volume support already enabled." +fi + +# Check if we enabled m2 volume support +setting="$(get_key_value $synoinfo ${smp})" +if [[ $enabled == "yes" ]]; then if [[ $setting == "yes" ]]; then echo -e "\nEnabled M.2 volume support." + else + echo -e "${Error}ERROR${Off} Failed to enable m2 volume support!" fi fi -# Edit synoinfo.conf to prevent DB updates -#if [[ $nodbupdate == "yes" ]]; then # For future use - file=/etc.defaults/synoinfo.conf - if [[ -f $file ]]; then - # Backup synoinfo.conf if needed - if [[ ! -f "$file.bak" ]]; then - if cp "$file" "$file.bak"; then - echo "Backed up synoinfo.conf to $(basename -- "${file}").bak" - else - echo -e "\e[41mERROR\e[0m Failed to backup $(basename -- "${file}")!" - exit 6 - fi - fi +# Edit synoinfo.conf to prevent drive db updates +dtu=drive_db_test_url +url="$(get_key_value $synoinfo ${dtu})" +disabled="" +if [[ $nodbupdate == "yes" ]]; then + if [[ ! $url ]]; then + # Add drive_db_test_url="127.0.0.1" + echo 'drive_db_test_url="127.0.0.1"' >> "$synoinfo" + disabled="yes" + elif [[ $url != "127.0.0.1" ]]; then + # Edit drive_db_test_url= + sed -i "s/drive_db_test_url=.*/drive_db_test_url=\"127.0.0.1\"/" "$synoinfo" >/dev/null + disabled="yes" + fi - url=$(get_key_value "$file" drive_db_test_url) # returns a linefeed if key doesn't exist - if [[ ! $url ]]; then - # Add drive_db_test_url=127.0.0.1 - echo 'drive_db_test_url="127.0.0.1"' >> "$file" - disabled="yes" - elif [[ $url != "127.0.0.1" ]]; then - # Edit drive_db_test_url= - sed -i "s/drive_db_test_url=.*/drive_db_test_url=\"127.0.0.1\"/" "$file" - disabled="yes" + # Check if we disabled drive db auto updates + url="$(get_key_value $synoinfo drive_db_test_url)" + if [[ $disabled == "yes" ]]; then + if [[ $url == "127.0.0.1" ]]; then + echo -e "\nDisabled drive db auto updates." + else + echo -e "${Error}ERROR${Off} Failed to disable drive db auto updates!" fi - - url=$(get_key_value "$file" drive_db_test_url) - if [[ $disabled == "yes" ]]; then - if [[ $url == "127.0.0.1" ]]; then - echo "Disabled drive db auto updates." - else - echo -e "\e[41mERROR\e[0m Failed to disable drive db auto updates!" - fi + fi +else + # Re-enable drive db updates + if [[ $url == "127.0.0.1" ]]; then + # Edit drive_db_test_url= + sed -z "s/drive_db_test_url=\"127\.0\.0\.1\"\n//" "$synoinfo" >/dev/null + #sed -i "s/drive_db_test_url=\"127\.0\.0\.1\"//" "$synoinfo" # works but leaves line feed + + # Check if we re-enabled drive db auto updates + url="$(get_key_value $synoinfo drive_db_test_url)" + if [[ $url != "127.0.0.1" ]]; then + echo -e "\nRe-enabled drive db auto updates." fi + else + echo -e "\nDrive db auto updates already enabled." fi -#fi +fi +#------------------------------------------------------------------------------ +# Finished + # Show the changes if [[ ${showedits,,} == "yes" ]]; then if [[ $dbtype -gt "6" ]];then