#!/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' " 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 /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