314 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			314 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
#!/command/with-contenv bashio
 | 
						|
# shellcheck shell=bash
 | 
						|
# ==============================================================================
 | 
						|
# Mounting external HD and modify the smb.conf
 | 
						|
# ==============================================================================
 | 
						|
declare moredisks
 | 
						|
declare autodisks
 | 
						|
declare tomountdisks
 | 
						|
declare interface
 | 
						|
declare ipaddress
 | 
						|
declare ssh_private_key
 | 
						|
declare remote_mount
 | 
						|
declare network_mount
 | 
						|
declare fstypes
 | 
						|
declare dev
 | 
						|
declare mntops
 | 
						|
declare reserved_names
 | 
						|
 | 
						|
function disk2label() { # $1 disk  return (label disk or id)
 | 
						|
     local disk=$1
 | 
						|
     if [[ $disk == id:* ]]; then
 | 
						|
          disk=${disk:3}
 | 
						|
          if [ -L /dev/disk/by-id/"$disk" ]; then
 | 
						|
               label=$(lsblk -no label /dev/disk/by-id/"$disk")
 | 
						|
               #               fstype=$(lsblk -no fstype /dev/disk/by-id/"$disk")
 | 
						|
               if [[ -n "$label" && -L "/dev/disk/by-label/$label" ]]; then
 | 
						|
                    bashio::log.info "Disk with id ${disk} is labeled $label so $label is used."
 | 
						|
                    disk="$label"
 | 
						|
                    #               elif [[ $fstype == apfs ]]; then
 | 
						|
                    #                    disk=$(apfsutil /dev/disk/by-id/"$disk" | awk -F "[, ]+" '/Name:/{print $2}')
 | 
						|
               else
 | 
						|
                    disk=$1
 | 
						|
               fi
 | 
						|
          else
 | 
						|
               bashio::log.warning "Disk with id ${disk} not found."
 | 
						|
               return 1
 | 
						|
          fi
 | 
						|
     else
 | 
						|
          blkid -L "$disk" >>/dev/null || {
 | 
						|
               bashio::log.warning "Disk with label ${disk} not found."
 | 
						|
               return 1
 | 
						|
          }
 | 
						|
     fi
 | 
						|
     echo "$disk"
 | 
						|
     return 0
 | 
						|
}
 | 
						|
 | 
						|
# Check for reserved mount name
 | 
						|
function reserved_mount_name() { # $1 disk
 | 
						|
     disk=$1
 | 
						|
     reserved_names=(config addons ssl share backup media all_addon_configs homeassistant)
 | 
						|
 | 
						|
     # Clean reserved name with disaled
 | 
						|
     for rdisk in "${reserved_names[@]}"; do
 | 
						|
          deleted=$(jq -r --arg share "${rdisk,,}" '.acl[] | select( (.share|ascii_upcase) == ($share|ascii_upcase) )  | select (.disabled) | .share' </data/options.json)
 | 
						|
          reserved_names=("${reserved_names[@]/$deleted/}")
 | 
						|
     done
 | 
						|
 | 
						|
     # Clean tomountdisks
 | 
						|
     for rdisk in "${reserved_names[@]}"; do
 | 
						|
          if [[ ${rdisk,,} = ${disk,,} ]]; then
 | 
						|
               tomountdisks=("${tomountdisks[@]/$disk/}")
 | 
						|
               return 0
 | 
						|
          fi
 | 
						|
     done
 | 
						|
}
 | 
						|
 | 
						|
# mount a disk from parameters
 | 
						|
function mount_disk() { # $1 disk $2 path $3 remote_mount $4 mount_options
 | 
						|
     disk=$1
 | 
						|
     path=$2
 | 
						|
     remote_mount=$3
 | 
						|
     mntops=$4
 | 
						|
     if [[ $disk == id:* ]]; then
 | 
						|
          bashio::log.debug "Disk ${disk:3} is an ID"
 | 
						|
          if [ -L "/dev/disk/by-uuid/${disk:3}" ]; then
 | 
						|
               dev=/dev/disk/by-uuid/${disk:3}
 | 
						|
               disk=${disk:3}
 | 
						|
          elif [ -L "/dev/disk/by-id/${disk:3}" ]; then
 | 
						|
               dev=/dev/disk/by-id/${disk:3}
 | 
						|
               disk=${disk:3}
 | 
						|
          elif [ -L "/dev/disk/by-partuuid/${disk:3}" ]; then
 | 
						|
               dev=/dev/disk/by-partuuid/${disk:3}
 | 
						|
               disk=${disk:3}
 | 
						|
          else
 | 
						|
               unset dev
 | 
						|
          fi
 | 
						|
     else
 | 
						|
          dev=$(blkid -L "$disk")
 | 
						|
     fi
 | 
						|
 | 
						|
     if [ ! ${dev:+1} ]; then
 | 
						|
          bashio::log.info "Disk ${disk} not found! <SKIP>"
 | 
						|
          return 0
 | 
						|
     fi
 | 
						|
 | 
						|
     mdisk=$(printf %b "$disk")
 | 
						|
 | 
						|
     mkdir -p "$path/$mdisk"
 | 
						|
     chmod a+rwx "$path/$mdisk"
 | 
						|
 | 
						|
     # check with findmnt if the disk is already mounted
 | 
						|
     if findmnt -n -o TARGET "$path/$mdisk" >/dev/null 2>&1; then
 | 
						|
          bashio::log.info "Disk ${mdisk} is already mounted"
 | 
						|
          echo "$path"/"$mdisk" >>/tmp/local_mount
 | 
						|
          return 0
 | 
						|
     else
 | 
						|
          # Check FS type and set relative options
 | 
						|
          fstype=$(lsblk "$dev" -no fstype)
 | 
						|
          options="${mntops}"
 | 
						|
          type="auto"
 | 
						|
          cmd="mount"
 | 
						|
          case "$fstype" in
 | 
						|
          exfat | vfat | msdos)
 | 
						|
               bashio::log.warning "Your ${mdisk} is ${fstype}. Permissions and ACL don't works and this is an EXPERIMENTAL support"
 | 
						|
               options="${options},umask=000"
 | 
						|
               ;;
 | 
						|
          ntfs)
 | 
						|
               bashio::log.warning "Your ${mdisk} is ${fstype}. This is an EXPERIMENTAL support"
 | 
						|
               options="${options},umask=000"
 | 
						|
               type="ntfs3"
 | 
						|
               ;;
 | 
						|
          apfs)
 | 
						|
               bashio::log.warning "Your ${mdisk} is ${fstype}. This is an EXPERIMENTAL support and work only in RO. Mount options not supported!"
 | 
						|
               type=""
 | 
						|
               options=""
 | 
						|
               cmd="mount.apfs"
 | 
						|
               ;;
 | 
						|
          esac
 | 
						|
 | 
						|
          # Create mount arg array
 | 
						|
          m_args=()
 | 
						|
          if [ -n "$type" ]; then
 | 
						|
               m_args+=("-t" $type)
 | 
						|
          fi
 | 
						|
          if [ -n "$options" ]; then
 | 
						|
               m_args+=("-o" $options)
 | 
						|
          fi
 | 
						|
          m_args+=("${dev}")
 | 
						|
 | 
						|
          bashio::log.debug "Mounting ${mdisk} of type ${fstype} with ${m_args[@]}"
 | 
						|
 | 
						|
          if [ "$remote_mount" = true ]; then
 | 
						|
               ssh root@"${ipaddress%/*}" -p 22222 -o "StrictHostKeyChecking no" "if findmnt '/mnt/data/supervisor/media/$mdisk ' >/dev/null; then echo 'Disk $mdisk already mounted on host' ; else  $cmd ${m_args[@]} '/mnt/data/supervisor/media/$mdisk'; fi" &&
 | 
						|
                    echo "$dev" >>/tmp/remote_mount
 | 
						|
          fi || bashio::log.warning "Host Mount ${mdisk}[${fstype}] Fail!" || :
 | 
						|
 | 
						|
          bashio::log.debug "Exec command: ${cmd} ${m_args[@]} \"${path}/${mdisk}\""
 | 
						|
          $cmd ${m_args[@]} "$path/$mdisk" &&
 | 
						|
               echo "$path"/"$mdisk" >>/tmp/local_mount &&
 | 
						|
               jq --arg dname "${mdisk}" --arg path "${path}/${mdisk}" --arg fs "${fstype}" ' . += {($dname | gsub( "-"; "_") | ascii_upcase ):{"path":$path,"fs":$fs}}' /tmp/local_mount.json >/tmp/local_mount.json.tmp &&
 | 
						|
               mv /tmp/local_mount.json.tmp /tmp/local_mount.json &&
 | 
						|
               bashio::log.info "Mount ${mdisk}[${fstype}] Success!"
 | 
						|
 | 
						|
     fi
 | 
						|
}
 | 
						|
 | 
						|
# Error for Operating System
 | 
						|
if ! [[ "$(bashio::info.operating_system)" =~ ^Home\ Assistant\ OS.* ]]; then
 | 
						|
     bashio::log.warning "Your operating system $(bashio::info.operating_system) is not supported! "
 | 
						|
     bashio::log.red "+------------------------------------------------------------------+"
 | 
						|
     bashio::log.red "| THIS ADDON IS DESIGNED FOR HOME ASSISTANT OPERATING SYSTEM ONLY! |"
 | 
						|
     bashio::log.red "| THIS ADDON IS DESIGNED FOR HOME ASSISTANT OPERATING SYSTEM ONLY! |"
 | 
						|
     bashio::log.red "| THIS ADDON IS DESIGNED FOR HOME ASSISTANT OPERATING SYSTEM ONLY! |"
 | 
						|
     bashio::log.red "| THIS ADDON IS DESIGNED FOR HOME ASSISTANT OPERATING SYSTEM ONLY! |"
 | 
						|
     bashio::log.red "| THIS ADDON IS DESIGNED FOR HOME ASSISTANT OPERATING SYSTEM ONLY! |"
 | 
						|
     bashio::log.red "+------------------------------------------------------------------+"
 | 
						|
     if bashio::config.exists 'meaning_of_life' && [[ $(bashio::config 'meaning_of_life') -eq 42 ]]; then
 | 
						|
          bashio::log.green "Deep Thought permission accepted!"
 | 
						|
     else
 | 
						|
          bashio::exit.nok "You can force this addon to run only if you known the meaning of life!"
 | 
						|
     fi
 | 
						|
fi
 | 
						|
 | 
						|
# Mount external drive
 | 
						|
bashio::log.info "Protection Mode is $(bashio::addon.protected)"
 | 
						|
# shellcheck disable=SC2091
 | 
						|
if $(bashio::addon.protected) && (bashio::config.has_value 'moredisks' || bashio::config.true 'automount'); then
 | 
						|
     bashio::log.warning "MoreDisk and Automount ignored because ADDON in Protected Mode!"
 | 
						|
     bashio::config.suggest "protected" "moredisk only work when Protection mode is disabled"
 | 
						|
elif bashio::config.has_value 'moredisks' || bashio::config.true 'automount'; then
 | 
						|
     bashio::log.info "MoreDisk or Automount option found!"
 | 
						|
 | 
						|
     # Check supported FS
 | 
						|
     for mfs in ntfs3 exfat btrfs xfs; do
 | 
						|
          modprobe $mfs || bashio::log.warning "$mfs module not available!"
 | 
						|
     done
 | 
						|
     fstypes=$(grep -v nodev </proc/filesystems | tr -d '\n')
 | 
						|
     bashio::log.blue "---------------------------------------------------"
 | 
						|
     bashio::log.green "Supported fs: ${fstypes}"
 | 
						|
     if grep -q fuseblk </proc/filesystems; then bashio::log.green "Supported fusefs: $(find /usr/sbin -name "mount*" | cut -c 17- | tr "\n" " " | sed s/fuse.//g)"; fi
 | 
						|
     bashio::log.blue "---------------------------------------------------"
 | 
						|
 | 
						|
     # Check Host Ssh config
 | 
						|
     remote_mount=false
 | 
						|
     network_mount=false
 | 
						|
     path=/mnt
 | 
						|
 | 
						|
     if bashio::config.true 'medialibrary.enable'; then
 | 
						|
          bashio::log.info "MediaLibrary option found!"
 | 
						|
          if bashio::config.is_empty 'medialibrary.ssh_private_key'; then
 | 
						|
               # Check OS Capability
 | 
						|
               features=$(bashio::info 'supervisor.info.features' '.features')
 | 
						|
               #bashio::log "Features ${features}"
 | 
						|
               if grep \"mount\" <<<"${features}" >/dev/null; then
 | 
						|
                    touch "/tmp/cifs_network"
 | 
						|
               else
 | 
						|
                    bashio::log.warning "Unsupported Mount Feature by system!"
 | 
						|
                    bashio::config.suggest "ssh_private_key" "Your host system don't upport mount feature\nSSH Private Key is required for enable medialibrary deprected feature."
 | 
						|
               fi
 | 
						|
          else
 | 
						|
 | 
						|
               bashio::log.red "+-------------------------------------------------------------------------------------+"
 | 
						|
               bashio::log.warning "|SSH Private Key *DEPRECATED WARNING* The use of old experimental system is deprecated|"
 | 
						|
               bashio::log.warning "|Remove the key and try the new system to mound /media and /share data disks          |"
 | 
						|
               bashio::log.red "+-------------------------------------------------------------------------------------+"
 | 
						|
 | 
						|
               interface=$(bashio::network.name)
 | 
						|
               ipaddress=$(bashio::network.ipv4_address "${interface}")
 | 
						|
               ssh_private_key=$(bashio::config 'medialibrary.ssh_private_key')
 | 
						|
               mkdir -p /root/.ssh
 | 
						|
               echo "${ssh_private_key}" >/root/.ssh/id_rsa
 | 
						|
               chmod ag-rw /root/.ssh/id_rsa
 | 
						|
 | 
						|
               if ssh root@"${ipaddress%/*}" -p 22222 -o "StrictHostKeyChecking no" "date"; then
 | 
						|
                    bashio::log.info "SSH connection to ${ipaddress%/*}:22222 OK"
 | 
						|
                    remote_mount=true
 | 
						|
                    path=/media
 | 
						|
               else
 | 
						|
                    bashio::log.warning "SSH connection to ${ipaddress%/*}:22222 FAILED"
 | 
						|
                    bashio::log.warning "MediaLibrary disabled due error in config!"
 | 
						|
               fi
 | 
						|
          fi
 | 
						|
     else
 | 
						|
          bashio::log.info "MediaLibrary disabled in config. Disk are mounted only for this addon!"
 | 
						|
     fi
 | 
						|
 | 
						|
     OIFS=$IFS
 | 
						|
     IFS=$'\n'
 | 
						|
 | 
						|
     ## List available Disk with Labels and Id
 | 
						|
     if bashio::config.true 'available_disks_log' || bashio::config.true 'automount'; then
 | 
						|
          bashio::log.blue "---------------------------------------------------"
 | 
						|
          #readarray -t autodisks < <(lsblk -E label -n -o label -i | sed -r '/^\s*$/d' | grep -v hassos)
 | 
						|
          readarray -t autodisks < <(/usr/bin/poetry -C /usr/local/bin/ run python /usr/local/bin/disklist.py)
 | 
						|
 | 
						|
          if [ ${#autodisks[@]} -eq 0 ]; then
 | 
						|
               bashio::log.info "No Disk with labels."
 | 
						|
          else
 | 
						|
               bashio::log.info "Available Disk Labels:"
 | 
						|
               for disk in "${autodisks[@]}"; do
 | 
						|
                    if [[ $disk == id:* ]]; then
 | 
						|
                         bashio::log.info "\t${disk}[$(lsblk $(blkid -U "${disk:3}") -no fstype)]"
 | 
						|
                    else
 | 
						|
                         bashio::log.info "\t${disk}[$(lsblk $(blkid -L "$disk") -no fstype)]"
 | 
						|
                    fi
 | 
						|
               done
 | 
						|
          fi
 | 
						|
          bashio::log.blue "---------------------------------------------------"
 | 
						|
     fi
 | 
						|
 | 
						|
     mnt_ops=($(bashio::config 'mountoptions'))
 | 
						|
     mnt_ops=$(
 | 
						|
          IFS=,
 | 
						|
          echo "${mnt_ops[*]}"
 | 
						|
     )
 | 
						|
 | 
						|
     moredisks=($(bashio::config 'moredisks'))
 | 
						|
     if [ ${#moredisks[@]} -eq 0 ]; then
 | 
						|
          bashio::log.info "No MoreDisks to mount"
 | 
						|
     else
 | 
						|
          bashio::log.info "MoreDisks to mount:\n" $(printf "\t%s\n" "${moredisks[@]}")
 | 
						|
          i=0
 | 
						|
          mmoredisks=()
 | 
						|
          for index in "${!moredisks[@]}"; do
 | 
						|
               tmpd=$(disk2label "${moredisks[$index]}") &&
 | 
						|
                    mmoredisks[$i]=$tmpd &&
 | 
						|
                    ((i = i + 1))
 | 
						|
          done
 | 
						|
          moredisks=("${mmoredisks[@]}")
 | 
						|
     fi
 | 
						|
 | 
						|
     if bashio::config.true 'automount' && [ ${#autodisks[@]} -gt 0 ]; then
 | 
						|
          bashio::log.info "Automount is Enabled!"
 | 
						|
          tomountdisks=("${autodisks[@]}" "${moredisks[@]}")
 | 
						|
          tomountdisks=($(sort -u <<<"${tomountdisks[*]}"))
 | 
						|
     else
 | 
						|
          tomountdisks=("${moredisks[@]}")
 | 
						|
     fi
 | 
						|
 | 
						|
     if [ ${#tomountdisks[@]} -gt 0 ]; then
 | 
						|
          bashio::log.magenta "---------------------------------------------------"
 | 
						|
          bashio::log.info "Checking Mounting disks for reserved names:\n" $(printf "\t%s\n" "${tomountdisks[@]}")
 | 
						|
          bashio::log.magenta "---------------------------------------------------"
 | 
						|
          for disk in "${tomountdisks[@]}"; do
 | 
						|
               reserved_mount_name "$disk" || bashio::log.warning "Fail to mount ${disk} due to reserved name!"
 | 
						|
          done
 | 
						|
     fi
 | 
						|
 | 
						|
     echo "{}" >/tmp/local_mount.json
 | 
						|
 | 
						|
     if [ ${#tomountdisks[@]} -gt 0 ]; then
 | 
						|
          bashio::log.magenta "---------------------------------------------------"
 | 
						|
          bashio::log.info "Mounting disks:\n" $(printf "\t%s\n" "${tomountdisks[@]}")
 | 
						|
          bashio::log.magenta "---------------------------------------------------"
 | 
						|
          for disk in "${tomountdisks[@]}"; do
 | 
						|
               mount_disk "$disk" "$path" "$remote_mount" "$mnt_ops" || bashio::log.warning "Fail to mount ${disk} ${mnt_ops} !"
 | 
						|
          done
 | 
						|
     fi
 | 
						|
     IFS=$OIFS
 | 
						|
 | 
						|
     echo "$path" >/tmp/mountpath
 | 
						|
fi
 |