mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-09-15 03:06:45 +00:00
The change journal exists so a sysadmin sees what ProxMenux changed on the host — its own configuration, packages and services — not how it uses the host or configures a guest. Several scripts recorded operations that are neither: disk passthrough to a VM, container conversions, VM import/export, mounting a share into an LXC. Those are restored to their original, uninstrumented form. Scripts that operate on the host while also installing a package now record only the package: format-disk keeps its exFAT-tools install, the UUP ISO builder its build dependencies, and the share/host scripts their packages, services and /etc/fstab writes, while the mount and unmount operations they used to log are dropped. The page now reads in three sections: what ProxMenux optimized after install (each function under its menu name), what its other host scripts changed (by script), and what it installed (packages and utilities, each referencing the script that installed it). A file reads as created or modified with its diff, a service shows its state transition, and the undo line appears only when a revert is possible.
1018 lines
41 KiB
Bash
1018 lines
41 KiB
Bash
#!/bin/bash
|
|
# ==========================================================
|
|
# ProxMenux - Samba Host Manager for Proxmox Host
|
|
# ==========================================================
|
|
# Author : MacRimi
|
|
# Copyright : (c) 2024 MacRimi
|
|
# License : GPL-3.0
|
|
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
|
|
# Version : 1.0
|
|
# ==========================================================
|
|
# Description:
|
|
# Mounts an external Samba (SMB / CIFS) share on the Proxmox
|
|
# host. User picks one or both methods:
|
|
# 1. As Proxmox storage (pvesm add cifs) → /mnt/pve/<id>
|
|
# 2. As host fstab mount → user-chosen path
|
|
#
|
|
# Method 2 is for users who want the host to mount the share
|
|
# for LXC bind-mounts WITHOUT exposing it as a Proxmox storage
|
|
# in the Datacenter UI. CIFS fstab mounts use
|
|
# uid=0,gid=0,file_mode=0777,dir_mode=0777 so an unprivileged
|
|
# LXC bind-mounting the path can read/write — no changes are
|
|
# made INSIDE the container.
|
|
#
|
|
# Credentials for fstab mounts are stored in a root-only
|
|
# credentials file (/etc/samba/credentials/<server>_<share>.cred)
|
|
# and referenced via the credentials= mount option. Plain text
|
|
# never lands in /etc/fstab.
|
|
#
|
|
# Features:
|
|
# - Auto-discover Samba servers on the local subnet
|
|
# (nmap on ports 139/445 + nmblookup for NetBIOS names).
|
|
# - Guest or username/password authentication.
|
|
# - Share listing via smbclient -L (filtered to Disk shares).
|
|
# - Content-type checklist (no rootdir — Proxmox does not
|
|
# support LXC rootfs on CIFS).
|
|
# - View, remove and connectivity-test for existing storages.
|
|
# ==========================================================
|
|
|
|
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
|
|
BASE_DIR="/usr/local/share/proxmenux"
|
|
UTILS_FILE="$BASE_DIR/utils.sh"
|
|
|
|
if [[ -f "$UTILS_FILE" ]]; then
|
|
source "$UTILS_FILE"
|
|
fi
|
|
|
|
if [[ -f "$LOCAL_SCRIPTS/global/pmx_journal.sh" ]]; then
|
|
source "$LOCAL_SCRIPTS/global/pmx_journal.sh"
|
|
fi
|
|
|
|
load_language
|
|
initialize_cache
|
|
|
|
if ! command -v pveversion >/dev/null 2>&1; then
|
|
dialog --backtitle "ProxMenux" --title "$(translate "Error")" \
|
|
--msgbox "$(translate "This script must be run on a Proxmox host.")" 8 60
|
|
exit 1
|
|
fi
|
|
|
|
# ==========================================================
|
|
# STORAGE CONFIG READER
|
|
# ==========================================================
|
|
get_storage_config() {
|
|
local storage_id="$1"
|
|
awk -v id="$storage_id" '
|
|
/^[a-z]+: / { found = ($0 ~ ": "id"$"); next }
|
|
found && /^[^ \t]/ { exit }
|
|
found { print }
|
|
' /etc/pve/storage.cfg
|
|
}
|
|
|
|
# ==========================================================
|
|
# SERVER DISCOVERY
|
|
# ==========================================================
|
|
|
|
discover_samba_servers() {
|
|
local FUNC_VERSION="1.0"
|
|
pmx_journal_context "discover_samba_servers" "$FUNC_VERSION"
|
|
|
|
show_proxmenux_logo
|
|
msg_title "$(translate "Add Samba Share as Proxmox Storage")"
|
|
msg_info "$(translate "Scanning network for Samba servers...")"
|
|
|
|
HOST_IP=$(hostname -I | awk '{print $1}')
|
|
NETWORK=$(echo "$HOST_IP" | cut -d. -f1-3).0/24
|
|
|
|
for pkg in nmap samba-common-bin; do
|
|
if ! which "${pkg%%-*}" >/dev/null 2>&1; then
|
|
pmx_install_pkg "$pkg" &>/dev/null
|
|
fi
|
|
done
|
|
|
|
SERVERS=$(nmap -p 139,445 --open "$NETWORK" 2>/dev/null | grep -B 4 -E "(139|445)/tcp open" | grep "Nmap scan report" | awk '{print $5}' | sort -u || true)
|
|
if [[ -z "$SERVERS" ]]; then
|
|
cleanup
|
|
whiptail --title "$(translate "No Servers Found")" \
|
|
--msgbox "$(translate "No Samba servers found on the network.")\n\n$(translate "You can add servers manually.")" 10 60
|
|
return 1
|
|
fi
|
|
|
|
SERVER_LINES=()
|
|
while IFS= read -r server; do
|
|
[[ -z "$server" ]] && continue
|
|
NB_NAME=$(nmblookup -A "$server" 2>/dev/null | awk '/<00> -.*B <ACTIVE>/ {print $1; exit}')
|
|
if [[ -z "$NB_NAME" || "$NB_NAME" == "$server" || "$NB_NAME" == "address" || "$NB_NAME" == "-" ]]; then
|
|
NB_NAME="Unknown"
|
|
fi
|
|
SERVER_LINES+=("$server|$NB_NAME ($server)")
|
|
done <<< "$SERVERS"
|
|
|
|
IFS=$'\n' SORTED=($(printf "%s\n" "${SERVER_LINES[@]}" | sort -t. -k1,1n -k2,2n -k3,3n -k4,4n))
|
|
|
|
OPTIONS=()
|
|
declare -A SERVER_IPS
|
|
i=1
|
|
for entry in "${SORTED[@]}"; do
|
|
server="${entry%%|*}"
|
|
label="${entry#*|}"
|
|
OPTIONS+=("$i" "$label")
|
|
SERVER_IPS["$i"]="$server"
|
|
((i++))
|
|
done
|
|
|
|
if [[ ${#OPTIONS[@]} -eq 0 ]]; then
|
|
cleanup
|
|
whiptail --title "$(translate "No Valid Servers")" --msgbox "$(translate "No accessible Samba servers found.")" 8 50
|
|
return 1
|
|
fi
|
|
|
|
msg_ok "$(translate "Samba servers detected")"
|
|
CHOICE=$(whiptail --backtitle "ProxMenux" --title "$(translate "Select Samba Server")" \
|
|
--menu "$(translate "Choose a Samba server:")" 20 80 10 "${OPTIONS[@]}" 3>&1 1>&2 2>&3)
|
|
|
|
if [[ -n "$CHOICE" ]]; then
|
|
SAMBA_SERVER="${SERVER_IPS[$CHOICE]}"
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
select_samba_server() {
|
|
METHOD=$(dialog --backtitle "ProxMenux" --title "$(translate "Samba Server Selection")" \
|
|
--menu "$(translate "How do you want to select the Samba server?")" 15 70 2 \
|
|
"auto" "$(translate "Auto-discover servers on network")" \
|
|
"manual" "$(translate "Enter server IP/hostname manually")" \
|
|
3>&1 1>&2 2>&3)
|
|
|
|
case "$METHOD" in
|
|
auto)
|
|
discover_samba_servers || return 1
|
|
;;
|
|
manual)
|
|
clear
|
|
SAMBA_SERVER=$(whiptail --inputbox "$(translate "Enter Samba server IP:")" \
|
|
10 60 --title "$(translate "Samba Server")" 3>&1 1>&2 2>&3)
|
|
[[ -z "$SAMBA_SERVER" ]] && return 1
|
|
;;
|
|
*)
|
|
return 1
|
|
;;
|
|
esac
|
|
return 0
|
|
}
|
|
|
|
# ==========================================================
|
|
# CREDENTIALS
|
|
# ==========================================================
|
|
|
|
get_samba_credentials() {
|
|
AUTH_TYPE=$(whiptail --title "$(translate "Authentication")" \
|
|
--menu "$(translate "Select authentication type:")" 12 60 2 \
|
|
"user" "$(translate "Username and password")" \
|
|
"guest" "$(translate "Guest access (no authentication)")" \
|
|
3>&1 1>&2 2>&3)
|
|
[[ $? -ne 0 ]] && return 1
|
|
|
|
if [[ "$AUTH_TYPE" == "guest" ]]; then
|
|
USE_GUEST=true
|
|
USERNAME=""
|
|
PASSWORD=""
|
|
return 0
|
|
fi
|
|
|
|
USE_GUEST=false
|
|
|
|
USERNAME=$(whiptail --inputbox "$(translate "Enter username:")" \
|
|
10 60 --title "$(translate "Samba Username")" 3>&1 1>&2 2>&3)
|
|
[[ $? -ne 0 || -z "$USERNAME" ]] && return 1
|
|
|
|
PASSWORD=$(whiptail --passwordbox "$(translate "Enter password:")" \
|
|
10 60 --title "$(translate "Samba Password")" 3>&1 1>&2 2>&3)
|
|
[[ $? -ne 0 ]] && return 1
|
|
|
|
return 0
|
|
}
|
|
|
|
# ==========================================================
|
|
# SHARE SELECTION
|
|
# ==========================================================
|
|
|
|
select_samba_share() {
|
|
if [[ "$USE_GUEST" == "true" ]]; then
|
|
SHARES=$(smbclient -L "$SAMBA_SERVER" -N 2>/dev/null | awk '/Disk/ {print $1}' | sort -u || true)
|
|
else
|
|
SHARES=$(smbclient -L "$SAMBA_SERVER" -U "$USERNAME%$PASSWORD" 2>/dev/null | awk '/Disk/ {print $1}' | sort -u || true)
|
|
fi
|
|
|
|
if [[ -z "$SHARES" ]]; then
|
|
whiptail --title "$(translate "No Available Shares")" \
|
|
--msgbox "$(translate "No accessible shares found.")\n\n$(translate "You can enter the share name manually.")" \
|
|
10 70
|
|
SAMBA_SHARE=$(whiptail --inputbox "$(translate "Enter Samba share name:")" \
|
|
10 60 --title "$(translate "Share Name")" 3>&1 1>&2 2>&3)
|
|
[[ -z "$SAMBA_SHARE" ]] && return 1
|
|
return 0
|
|
fi
|
|
|
|
OPTIONS=()
|
|
while IFS= read -r share; do
|
|
[[ -n "$share" ]] && OPTIONS+=("$share" "$(translate "Samba share")")
|
|
done <<< "$SHARES"
|
|
|
|
if [[ ${#OPTIONS[@]} -eq 0 ]]; then
|
|
SAMBA_SHARE=$(whiptail --inputbox "$(translate "Enter Samba share name:")" \
|
|
10 60 --title "$(translate "Share Name")" 3>&1 1>&2 2>&3)
|
|
[[ -z "$SAMBA_SHARE" ]] && return 1
|
|
return 0
|
|
fi
|
|
|
|
SAMBA_SHARE=$(whiptail --title "$(translate "Select Samba Share")" \
|
|
--menu "$(translate "Choose a share to mount:")" 20 70 10 "${OPTIONS[@]}" 3>&1 1>&2 2>&3)
|
|
[[ -n "$SAMBA_SHARE" ]] && return 0 || return 1
|
|
}
|
|
|
|
# ==========================================================
|
|
# STORAGE CONFIGURATION
|
|
# ==========================================================
|
|
|
|
configure_cifs_storage() {
|
|
STORAGE_ID=$(whiptail --inputbox "$(translate "Enter storage ID for Proxmox:")" \
|
|
10 60 "cifs-$(echo "$SAMBA_SERVER" | tr '.' '-')" \
|
|
--title "$(translate "Storage ID")" 3>&1 1>&2 2>&3)
|
|
[[ $? -ne 0 ]] && return 1
|
|
[[ -z "$STORAGE_ID" ]] && STORAGE_ID="cifs-$(echo "$SAMBA_SERVER" | tr '.' '-')"
|
|
|
|
if [[ ! "$STORAGE_ID" =~ ^[a-zA-Z0-9][a-zA-Z0-9_-]*$ ]]; then
|
|
whiptail --msgbox "$(translate "Invalid storage ID. Use only letters, numbers, hyphens and underscores.")" 8 70
|
|
return 1
|
|
fi
|
|
|
|
local raw_content
|
|
raw_content=$(dialog --backtitle "ProxMenux" \
|
|
--title "$(translate "Content Types")" \
|
|
--checklist "\n$(translate "Select content types for this storage:")\n$(translate "(Import is selected by default — required for disk image imports)")" 18 65 7 \
|
|
"import" "$(translate "Import — disk image imports")" on \
|
|
"backup" "$(translate "Backup — VM and CT backups")" off \
|
|
"iso" "$(translate "ISO image — installation images")" off \
|
|
"vztmpl" "$(translate "Container template— LXC templates")" off \
|
|
"images" "$(translate "Disk image — VM disk images")" off \
|
|
"snippets" "$(translate "Snippets — hook scripts / config")" off \
|
|
3>&1 1>&2 2>&3)
|
|
[[ $? -ne 0 ]] && return 1
|
|
|
|
# Convert dialog checklist output (quoted space-separated) to comma-separated
|
|
MOUNT_CONTENT=$(echo "$raw_content" | tr -d '"' | tr -s ' ' ',' | sed 's/^,//;s/,$//')
|
|
[[ -z "$MOUNT_CONTENT" ]] && MOUNT_CONTENT="import"
|
|
|
|
# Warn if images selected (CIFS locking issues with VM disks)
|
|
if echo "$MOUNT_CONTENT" | grep -q "images"; then
|
|
whiptail --title "$(translate "Warning: Disk Images on CIFS")" \
|
|
--msgbox "$(translate "You selected 'Disk image' content on a CIFS/SMB storage.")\n\n$(translate "CIFS can cause file locking issues with VM disk operations.")\n$(translate "NFS is recommended for VM disk image storage.")\n\n$(translate "Continuing with your selection.")" \
|
|
12 70
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
add_proxmox_cifs_storage() {
|
|
local storage_id="$1"
|
|
local server="$2"
|
|
local share="$3"
|
|
local content="${4:-import}"
|
|
local FUNC_VERSION="1.0"
|
|
pmx_journal_context "add_proxmox_cifs_storage" "$FUNC_VERSION"
|
|
|
|
if ! command -v pvesm >/dev/null 2>&1; then
|
|
msg_error "$(translate "pvesm command not found. This should not happen on Proxmox.")"
|
|
return 1
|
|
fi
|
|
|
|
msg_ok "$(translate "pvesm command found")"
|
|
|
|
if pvesm status "$storage_id" >/dev/null 2>&1; then
|
|
msg_warn "$(translate "Storage ID already exists:") $storage_id"
|
|
if ! whiptail --yesno "$(translate "Storage ID already exists. Do you want to remove and recreate it?")" \
|
|
8 60 --title "$(translate "Storage Exists")"; then
|
|
return 0
|
|
fi
|
|
pvesm remove "$storage_id" 2>/dev/null || true
|
|
fi
|
|
|
|
msg_ok "$(translate "Storage ID is available")"
|
|
msg_info "$(translate "Adding CIFS storage to Proxmox...")"
|
|
|
|
local pvesm_result pvesm_output
|
|
if [[ "$USE_GUEST" == "true" ]]; then
|
|
pvesm_output=$(pvesm add cifs "$storage_id" \
|
|
--server "$server" \
|
|
--share "$share" \
|
|
--content "$content" 2>&1)
|
|
pvesm_result=$?
|
|
else
|
|
pvesm_output=$(pvesm add cifs "$storage_id" \
|
|
--server "$server" \
|
|
--share "$share" \
|
|
--username "$USERNAME" \
|
|
--password "$PASSWORD" \
|
|
--content "$content" 2>&1)
|
|
pvesm_result=$?
|
|
fi
|
|
|
|
if [[ $pvesm_result -eq 0 ]]; then
|
|
msg_ok "$(translate "CIFS storage added successfully to Proxmox!")"
|
|
echo -e ""
|
|
echo -e "${TAB}${BOLD}$(translate "Storage Added:")${CL}"
|
|
echo -e "${TAB}${BGN}$(translate "Storage ID:")${CL} ${BL}$storage_id${CL}"
|
|
echo -e "${TAB}${BGN}$(translate "Server:")${CL} ${BL}$server${CL}"
|
|
echo -e "${TAB}${BGN}$(translate "Share:")${CL} ${BL}$share${CL}"
|
|
echo -e "${TAB}${BGN}$(translate "Content Types:")${CL} ${BL}$content${CL}"
|
|
echo -e "${TAB}${BGN}$(translate "Authentication:")${CL} ${BL}$([ "$USE_GUEST" == "true" ] && echo "Guest" || echo "User: $USERNAME")${CL}"
|
|
echo -e "${TAB}${BGN}$(translate "Mount Path:")${CL} ${BL}/mnt/pve/$storage_id${CL}"
|
|
echo -e ""
|
|
msg_ok "$(translate "Storage is now available in Proxmox web interface under Datacenter > Storage")"
|
|
return 0
|
|
else
|
|
msg_error "$(translate "Failed to add CIFS storage to Proxmox.")"
|
|
echo -e "${TAB}$(translate "Error details:"): $pvesm_output"
|
|
echo -e ""
|
|
msg_info2 "$(translate "You can add it manually through:")"
|
|
echo -e "${TAB}• $(translate "Proxmox web interface: Datacenter > Storage > Add > SMB/CIFS")"
|
|
echo -e "${TAB}• pvesm add cifs $storage_id --server $server --share $share --username USER --password PASS --content $content"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# ==========================================================
|
|
# MAIN OPERATIONS
|
|
# ==========================================================
|
|
|
|
# ==========================================================
|
|
# FSTAB MOUNT (host-only, NOT as Proxmox storage)
|
|
# ==========================================================
|
|
|
|
# Pick a mount path on the host. Default is /mnt/<share-name>.
|
|
# Validates the path is absolute and not already in use.
|
|
select_host_cifs_mount_path() {
|
|
local default_name="$SAMBA_SHARE"
|
|
[[ -z "$default_name" ]] && default_name="cifs_share"
|
|
|
|
while true; do
|
|
HOST_MOUNT_PATH=$(whiptail --inputbox \
|
|
"$(translate "Enter the host mount path:")\n\n$(translate "Default location is /mnt/<name>. The share will be mounted here on the host with open permissions so an unprivileged LXC can bind-mount and write to it. For LXC access, bind-mount this path with the LXC Mount Manager.")" \
|
|
15 70 "/mnt/$default_name" \
|
|
--title "$(translate "Host Mount Path")" 3>&1 1>&2 2>&3)
|
|
[[ $? -ne 0 ]] && return 1
|
|
[[ -z "$HOST_MOUNT_PATH" ]] && HOST_MOUNT_PATH="/mnt/$default_name"
|
|
|
|
if [[ ! "$HOST_MOUNT_PATH" =~ ^/.+ ]]; then
|
|
whiptail --msgbox "$(translate "Mount path must be an absolute path starting with /")" 8 60
|
|
continue
|
|
fi
|
|
|
|
if mount | grep -q " on $HOST_MOUNT_PATH "; then
|
|
whiptail --msgbox "$(translate "Something is already mounted at:") $HOST_MOUNT_PATH\n\n$(translate "Choose a different path or unmount it first.")" 10 70
|
|
continue
|
|
fi
|
|
|
|
if grep -qE "[[:space:]]${HOST_MOUNT_PATH}[[:space:]]" /etc/fstab 2>/dev/null; then
|
|
if ! whiptail --yesno "$(translate "An fstab entry already exists for:") $HOST_MOUNT_PATH\n\n$(translate "Replace it?")" 10 70 \
|
|
--title "$(translate "fstab entry exists")"; then
|
|
continue
|
|
fi
|
|
FSTAB_REPLACE=1
|
|
else
|
|
FSTAB_REPLACE=0
|
|
fi
|
|
break
|
|
done
|
|
return 0
|
|
}
|
|
|
|
# Pick CIFS mount options for the fstab entry.
|
|
# Open uid/gid/file_mode are always included so unprivileged LXC
|
|
# bind-mounts can read/write without touching the container.
|
|
select_cifs_mount_options() {
|
|
local base="uid=0,gid=0,file_mode=0777,dir_mode=0777,iocharset=utf8,nofail,_netdev"
|
|
local choice
|
|
choice=$(dialog --backtitle "ProxMenux" \
|
|
--title "$(translate "Mount Options")" \
|
|
--menu "$(translate "Select mount options. Open uid/gid/file_mode are always applied so unprivileged LXC bind-mounts can write:")" 15 78 4 \
|
|
"1" "$(translate "Read/Write (default)")" \
|
|
"2" "$(translate "Read-only")" \
|
|
"3" "$(translate "Custom")" \
|
|
3>&1 1>&2 2>&3)
|
|
[[ $? -ne 0 ]] && return 1
|
|
|
|
case "$choice" in
|
|
1) CIFS_MOUNT_OPTS="rw,${base}" ;;
|
|
2) CIFS_MOUNT_OPTS="ro,${base/file_mode=0777,dir_mode=0777/file_mode=0555,dir_mode=0555}" ;;
|
|
3)
|
|
CIFS_MOUNT_OPTS=$(whiptail --inputbox \
|
|
"$(translate "Enter custom CIFS mount options (open uid/gid/file_mode strongly recommended for LXC bind-mounts):")" \
|
|
12 78 "rw,${base}" \
|
|
--title "$(translate "Custom Options")" 3>&1 1>&2 2>&3)
|
|
[[ $? -ne 0 ]] && return 1
|
|
[[ -z "$CIFS_MOUNT_OPTS" ]] && CIFS_MOUNT_OPTS="rw,${base}"
|
|
;;
|
|
esac
|
|
return 0
|
|
}
|
|
|
|
# Write a root-only credentials file for the fstab mount.
|
|
# Sets HOST_CRED_FILE on success, or empty string for guest mode.
|
|
write_host_credentials_file() {
|
|
local FUNC_VERSION="1.0"
|
|
pmx_journal_context "write_host_credentials_file" "$FUNC_VERSION"
|
|
|
|
if [[ "$USE_GUEST" == "true" ]]; then
|
|
HOST_CRED_FILE=""
|
|
return 0
|
|
fi
|
|
local creds_dir="/etc/samba/credentials"
|
|
mkdir -p "$creds_dir"
|
|
chmod 0700 "$creds_dir"
|
|
HOST_CRED_FILE="${creds_dir}/$(echo "${SAMBA_SERVER}_${SAMBA_SHARE}" | tr -c 'A-Za-z0-9._-' '_').cred"
|
|
pmx_write_file "$HOST_CRED_FILE" <<EOF
|
|
username=${USERNAME}
|
|
password=${PASSWORD}
|
|
EOF
|
|
chmod 0600 "$HOST_CRED_FILE"
|
|
return 0
|
|
}
|
|
|
|
# Mount the CIFS share on the host and persist to /etc/fstab.
|
|
# Permission tweaks happen on the host side ONLY — never inside any LXC.
|
|
mount_cifs_via_fstab() {
|
|
local server="$1"
|
|
local share="$2"
|
|
local mount_path="$3"
|
|
local base_opts="$4"
|
|
local replace="$5"
|
|
local cred_file="$6"
|
|
local use_guest="$7"
|
|
local FUNC_VERSION="1.0"
|
|
pmx_journal_context "mount_cifs_via_fstab" "$FUNC_VERSION"
|
|
|
|
msg_info "$(translate "Preparing host mount...")"
|
|
|
|
if [[ ! -d "$mount_path" ]]; then
|
|
if ! mkdir -p "$mount_path" 2>/dev/null; then
|
|
msg_error "$(translate "Failed to create mount point:") $mount_path"
|
|
return 1
|
|
fi
|
|
fi
|
|
msg_ok "$(translate "Mount point ready:") $mount_path"
|
|
|
|
local mount_opts="$base_opts"
|
|
if [[ "$use_guest" == "true" ]]; then
|
|
mount_opts="${mount_opts},guest"
|
|
else
|
|
mount_opts="${mount_opts},credentials=${cred_file}"
|
|
fi
|
|
|
|
msg_info "$(translate "Mounting CIFS share...")"
|
|
if ! mount -t cifs -o "$mount_opts" "//${server}/${share}" "$mount_path" >/dev/null 2>&1; then
|
|
msg_error "$(translate "Failed to mount CIFS share on host.")"
|
|
return 1
|
|
fi
|
|
msg_ok "$(translate "CIFS share mounted at:") $mount_path"
|
|
|
|
if touch "$mount_path/.proxmenux_write_test" 2>/dev/null; then
|
|
rm -f "$mount_path/.proxmenux_write_test" 2>/dev/null
|
|
msg_ok "$(translate "Host write access confirmed.")"
|
|
else
|
|
msg_warn "$(translate "No host write access — server-side ACL. Continuing anyway.")"
|
|
fi
|
|
|
|
# Persist in /etc/fstab.
|
|
if [[ "$replace" == "1" ]]; then
|
|
pmx_edit_file /etc/fstab "\|[[:space:]]${mount_path}[[:space:]]|d"
|
|
fi
|
|
echo "//${server}/${share} $mount_path cifs $mount_opts 0 0" | pmx_append_file /etc/fstab
|
|
msg_ok "$(translate "Added to /etc/fstab.")"
|
|
|
|
systemctl daemon-reload 2>/dev/null || true
|
|
|
|
echo -e ""
|
|
echo -e "${TAB}${BOLD}$(translate "Host fstab Mount:")${CL}"
|
|
echo -e "${TAB}${BGN}$(translate "Server:")${CL} ${BL}$server${CL}"
|
|
echo -e "${TAB}${BGN}$(translate "Share:")${CL} ${BL}$share${CL}"
|
|
echo -e "${TAB}${BGN}$(translate "Mount path:")${CL} ${BL}$mount_path${CL}"
|
|
echo -e "${TAB}${BGN}$(translate "Auth:")${CL} ${BL}$([ "$use_guest" == "true" ] && echo Guest || echo "User ($cred_file)")${CL}"
|
|
echo -e "${TAB}${BGN}$(translate "Persistent:")${CL} ${BL}$(translate "yes (survives reboot)")${CL}"
|
|
echo -e ""
|
|
msg_info2 "$(translate "To use this share from an LXC, bind-mount it via:")"
|
|
echo -e "${TAB} pct set <ctid> -mpN $mount_path,mp=<container-path>,shared=1,backup=0"
|
|
echo -e "${TAB} $(translate "or use the ProxMenux LXC Mount Manager.")"
|
|
|
|
return 0
|
|
}
|
|
|
|
# ==========================================================
|
|
# MOUNT METHOD SELECTION
|
|
# ==========================================================
|
|
|
|
# Show a checklist with the two mount methods (pvesm / fstab).
|
|
# User must mark at least one and press OK; if none is marked,
|
|
# loop and show the dialog again. Cancel exits the flow.
|
|
# Sets MODE_PVESM and MODE_FSTAB to 0 or 1 on success.
|
|
select_cifs_mount_methods() {
|
|
MODE_PVESM=0
|
|
MODE_FSTAB=0
|
|
|
|
while true; do
|
|
local result
|
|
result=$(dialog --backtitle "ProxMenux" \
|
|
--title "$(translate "Mount Method")" \
|
|
--checklist "\n$(translate "Choose how to mount the Samba share on this host. Mark one or both options:")\n\n$(translate "• Proxmox storage (pvesm): visible in Datacenter > Storage, mount at /mnt/pve/<id>")\n$(translate "• Host fstab: mounted with open uid/gid/file_mode at a path you choose, ideal for LXC bind-mounts")\n$(translate "• Both: two independent CIFS mounts (one for Proxmox UI, one for LXC bind-mounts with open perms)")" 20 80 2 \
|
|
"pvesm" "$(translate "As Proxmox storage")" off \
|
|
"fstab" "$(translate "As host fstab mount only")" off \
|
|
3>&1 1>&2 2>&3)
|
|
local rc=$?
|
|
[[ $rc -ne 0 ]] && return 1 # Cancel → abort the whole flow
|
|
|
|
if echo "$result" | grep -qw "pvesm"; then MODE_PVESM=1; fi
|
|
if echo "$result" | grep -qw "fstab"; then MODE_FSTAB=1; fi
|
|
|
|
if [[ "$MODE_PVESM" == "1" || "$MODE_FSTAB" == "1" ]]; then
|
|
return 0
|
|
fi
|
|
|
|
whiptail --msgbox "$(translate "Please mark at least one option, or press Cancel to exit.")" 8 70
|
|
done
|
|
}
|
|
|
|
# ==========================================================
|
|
# MAIN OPERATIONS
|
|
# ==========================================================
|
|
|
|
mount_cifs_share() {
|
|
local FUNC_VERSION="1.0"
|
|
pmx_journal_context "mount_cifs_share" "$FUNC_VERSION"
|
|
|
|
if ! which smbclient >/dev/null 2>&1; then
|
|
msg_info "$(translate "Installing Samba client tools...")"
|
|
apt-get update &>/dev/null
|
|
pmx_install_pkg cifs-utils smbclient &>/dev/null
|
|
msg_ok "$(translate "Samba client tools installed")"
|
|
fi
|
|
|
|
# Step 1: Select server
|
|
select_samba_server || return
|
|
|
|
# Step 2: Get credentials
|
|
get_samba_credentials || return
|
|
|
|
# Step 3: Select share
|
|
select_samba_share || return
|
|
|
|
# Step 4: Pick mount method(s) — pvesm, fstab, or both
|
|
select_cifs_mount_methods || return
|
|
|
|
# Step 5a: If pvesm selected, gather storage params
|
|
if [[ "$MODE_PVESM" == "1" ]]; then
|
|
configure_cifs_storage || return
|
|
fi
|
|
|
|
# Step 5b: If fstab selected, gather host mount params + write credentials file
|
|
if [[ "$MODE_FSTAB" == "1" ]]; then
|
|
select_host_cifs_mount_path || return
|
|
select_cifs_mount_options || return
|
|
write_host_credentials_file || return
|
|
fi
|
|
|
|
# Step 6: Apply
|
|
show_proxmenux_logo
|
|
msg_title "$(translate "Mount Samba Share on Host")"
|
|
msg_ok "$(translate "Server:") $SAMBA_SERVER"
|
|
msg_ok "$(translate "Share:") $SAMBA_SHARE"
|
|
msg_ok "$(translate "Auth:") $([ "$USE_GUEST" == "true" ] && echo "Guest" || echo "User: $USERNAME")"
|
|
if [[ "$MODE_PVESM" == "1" ]]; then
|
|
msg_ok "$(translate "Method:") pvesm ($(translate "Storage ID:") $STORAGE_ID, $(translate "content:") $MOUNT_CONTENT)"
|
|
fi
|
|
if [[ "$MODE_FSTAB" == "1" ]]; then
|
|
msg_ok "$(translate "Method:") fstab ($(translate "Mount path:") $HOST_MOUNT_PATH)"
|
|
fi
|
|
echo -e ""
|
|
|
|
local overall_rc=0
|
|
if [[ "$MODE_PVESM" == "1" ]]; then
|
|
if ! add_proxmox_cifs_storage "$STORAGE_ID" "$SAMBA_SERVER" "$SAMBA_SHARE" "$MOUNT_CONTENT"; then
|
|
overall_rc=1
|
|
fi
|
|
echo -e ""
|
|
fi
|
|
if [[ "$MODE_FSTAB" == "1" ]]; then
|
|
if ! mount_cifs_via_fstab "$SAMBA_SERVER" "$SAMBA_SHARE" "$HOST_MOUNT_PATH" \
|
|
"$CIFS_MOUNT_OPTS" "$FSTAB_REPLACE" "$HOST_CRED_FILE" "$USE_GUEST"; then
|
|
overall_rc=1
|
|
fi
|
|
fi
|
|
|
|
echo -e ""
|
|
if [[ "$overall_rc" == "0" ]]; then
|
|
msg_success "$(translate "Press Enter to continue...")"
|
|
else
|
|
msg_warn "$(translate "Some operations failed — review messages above. Press Enter to continue...")"
|
|
fi
|
|
read -r
|
|
}
|
|
|
|
# ==========================================================
|
|
# FSTAB ENTRY DISCOVERY (host mounts NOT registered with pvesm)
|
|
# ==========================================================
|
|
|
|
# Print every CIFS entry in /etc/fstab as: server|share|mount_path|opts
|
|
# Skips comments and blank lines.
|
|
list_cifs_fstab_entries() {
|
|
awk '
|
|
/^[[:space:]]*#/ { next }
|
|
/^[[:space:]]*$/ { next }
|
|
$3 == "cifs" {
|
|
# $1 = //server/share, $2 = mount path, $4 = opts
|
|
sub(/^\/\//, "", $1)
|
|
split($1, srv_sh, "/")
|
|
print srv_sh[1] "|" srv_sh[2] "|" $2 "|" $4
|
|
}
|
|
' /etc/fstab 2>/dev/null
|
|
}
|
|
|
|
# Echo "active" if the given path is currently mounted, "inactive" otherwise.
|
|
check_mount_state() {
|
|
local path="$1"
|
|
if mount | grep -q " on ${path} type "; then
|
|
echo "active"
|
|
else
|
|
echo "inactive"
|
|
fi
|
|
}
|
|
|
|
view_cifs_storages() {
|
|
show_proxmenux_logo
|
|
msg_title "$(translate "CIFS Mounts on Host")"
|
|
|
|
echo "=================================================="
|
|
echo ""
|
|
|
|
# ---- Proxmox storages (pvesm) ----
|
|
local CIFS_STORAGES=""
|
|
if command -v pvesm >/dev/null 2>&1; then
|
|
CIFS_STORAGES=$(pvesm status 2>/dev/null | awk '$2 == "cifs" {print $1, $3}')
|
|
fi
|
|
|
|
if [[ -z "$CIFS_STORAGES" ]]; then
|
|
msg_warn "$(translate "No CIFS Proxmox storages configured.")"
|
|
else
|
|
echo -e "${BOLD}$(translate "CIFS Proxmox storages (pvesm):")${CL}"
|
|
echo ""
|
|
while IFS=" " read -r storage_id storage_status; do
|
|
[[ -z "$storage_id" ]] && continue
|
|
local storage_info server share content username
|
|
storage_info=$(get_storage_config "$storage_id")
|
|
server=$(echo "$storage_info" | awk '$1 == "server" {print $2}')
|
|
share=$(echo "$storage_info" | awk '$1 == "share" {print $2}')
|
|
content=$(echo "$storage_info" | awk '$1 == "content" {print $2}')
|
|
username=$(echo "$storage_info" | awk '$1 == "username" {print $2}')
|
|
|
|
echo -e "${TAB}${BOLD}$storage_id${CL} ${TAB}[pvesm]"
|
|
echo -e "${TAB} ${BGN}$(translate "Server:")${CL} ${BL}$server${CL}"
|
|
echo -e "${TAB} ${BGN}$(translate "Share:")${CL} ${BL}$share${CL}"
|
|
echo -e "${TAB} ${BGN}$(translate "Content:")${CL} ${BL}$content${CL}"
|
|
if [[ -n "$username" ]]; then
|
|
echo -e "${TAB} ${BGN}$(translate "Username:")${CL} ${BL}$username${CL}"
|
|
else
|
|
echo -e "${TAB} ${BGN}$(translate "Auth:")${CL} ${BL}Guest${CL}"
|
|
fi
|
|
echo -e "${TAB} ${BGN}$(translate "Mount Path:")${CL} ${BL}/mnt/pve/$storage_id${CL}"
|
|
if [[ "$storage_status" == "active" ]]; then
|
|
echo -e "${TAB} ${BGN}$(translate "Status:")${CL} ${GN}$(translate "Active")${CL}"
|
|
else
|
|
echo -e "${TAB} ${BGN}$(translate "Status:")${CL} ${RD}$storage_status${CL}"
|
|
fi
|
|
echo ""
|
|
done <<< "$CIFS_STORAGES"
|
|
fi
|
|
|
|
# ---- Host fstab mounts ----
|
|
local FSTAB_ENTRIES
|
|
FSTAB_ENTRIES=$(list_cifs_fstab_entries)
|
|
|
|
if [[ -z "$FSTAB_ENTRIES" ]]; then
|
|
echo -e "${BOLD}$(translate "Host fstab CIFS mounts:")${CL} $(translate "(none)")"
|
|
else
|
|
echo -e "${BOLD}$(translate "Host fstab CIFS mounts (not registered with pvesm):")${CL}"
|
|
echo ""
|
|
while IFS="|" read -r server share mount_path opts; do
|
|
[[ -z "$mount_path" ]] && continue
|
|
local mstate
|
|
mstate=$(check_mount_state "$mount_path")
|
|
|
|
# Detect credentials/guest from opts
|
|
local auth_str="Guest"
|
|
if echo "$opts" | grep -q "credentials="; then
|
|
local cred_file
|
|
cred_file=$(echo "$opts" | grep -oE "credentials=[^,]+" | cut -d= -f2)
|
|
auth_str="User ($cred_file)"
|
|
fi
|
|
|
|
echo -e "${TAB}${BOLD}$(basename "$mount_path")${CL} ${TAB}[fstab]"
|
|
echo -e "${TAB} ${BGN}$(translate "Server:")${CL} ${BL}$server${CL}"
|
|
echo -e "${TAB} ${BGN}$(translate "Share:")${CL} ${BL}$share${CL}"
|
|
echo -e "${TAB} ${BGN}$(translate "Mount Path:")${CL} ${BL}$mount_path${CL}"
|
|
echo -e "${TAB} ${BGN}$(translate "Auth:")${CL} ${BL}$auth_str${CL}"
|
|
echo -e "${TAB} ${BGN}$(translate "Options:")${CL} ${BL}$opts${CL}"
|
|
if [[ "$mstate" == "active" ]]; then
|
|
echo -e "${TAB} ${BGN}$(translate "Status:")${CL} ${GN}$(translate "Active")${CL}"
|
|
else
|
|
echo -e "${TAB} ${BGN}$(translate "Status:")${CL} ${RD}$(translate "Inactive (entry in fstab, not currently mounted)")${CL}"
|
|
fi
|
|
echo ""
|
|
done <<< "$FSTAB_ENTRIES"
|
|
fi
|
|
|
|
echo ""
|
|
msg_success "$(translate "Press Enter to continue...")"
|
|
read -r
|
|
}
|
|
|
|
remove_cifs_storage() {
|
|
local FUNC_VERSION="1.0"
|
|
pmx_journal_context "remove_cifs_storage" "$FUNC_VERSION"
|
|
|
|
local OPTIONS=()
|
|
local has_pvesm=0
|
|
local has_fstab=0
|
|
|
|
# pvesm-registered CIFS storages
|
|
if command -v pvesm >/dev/null 2>&1; then
|
|
local CIFS_STORAGES
|
|
CIFS_STORAGES=$(pvesm status 2>/dev/null | awk '$2 == "cifs" {print $1}')
|
|
if [[ -n "$CIFS_STORAGES" ]]; then
|
|
has_pvesm=1
|
|
while IFS= read -r storage_id; do
|
|
[[ -z "$storage_id" ]] && continue
|
|
local storage_info server share
|
|
storage_info=$(get_storage_config "$storage_id")
|
|
server=$(echo "$storage_info" | awk '$1 == "server" {print $2}')
|
|
share=$(echo "$storage_info" | awk '$1 == "share" {print $2}')
|
|
OPTIONS+=("pvesm:$storage_id" "[pvesm] $storage_id ($server/$share)")
|
|
done <<< "$CIFS_STORAGES"
|
|
fi
|
|
fi
|
|
|
|
# fstab-only CIFS mounts
|
|
local FSTAB_ENTRIES
|
|
FSTAB_ENTRIES=$(list_cifs_fstab_entries)
|
|
if [[ -n "$FSTAB_ENTRIES" ]]; then
|
|
has_fstab=1
|
|
while IFS="|" read -r server share mount_path opts; do
|
|
[[ -z "$mount_path" ]] && continue
|
|
OPTIONS+=("fstab:$mount_path" "[fstab] $mount_path ($server/$share)")
|
|
done <<< "$FSTAB_ENTRIES"
|
|
fi
|
|
|
|
if [[ "$has_pvesm" == "0" && "$has_fstab" == "0" ]]; then
|
|
dialog --backtitle "ProxMenux" --title "$(translate "Nothing to remove")" \
|
|
--msgbox "\n$(translate "No CIFS Proxmox storage and no CIFS fstab mount found on this host.")" 9 70
|
|
return
|
|
fi
|
|
|
|
local SELECTED
|
|
SELECTED=$(dialog --backtitle "ProxMenux" --title "$(translate "Remove CIFS Mount")" \
|
|
--menu "$(translate "Select the entry to remove. [pvesm] entries are removed from Proxmox storage; [fstab] entries are unmounted, removed from /etc/fstab and have their credentials file deleted.")" \
|
|
20 90 12 \
|
|
"${OPTIONS[@]}" 3>&1 1>&2 2>&3)
|
|
[[ -z "$SELECTED" ]] && return
|
|
|
|
local kind="${SELECTED%%:*}"
|
|
local target="${SELECTED#*:}"
|
|
|
|
case "$kind" in
|
|
pvesm)
|
|
local storage_info server share content username
|
|
storage_info=$(get_storage_config "$target")
|
|
server=$(echo "$storage_info" | awk '$1 == "server" {print $2}')
|
|
share=$(echo "$storage_info" | awk '$1 == "share" {print $2}')
|
|
content=$(echo "$storage_info" | awk '$1 == "content" {print $2}')
|
|
username=$(echo "$storage_info" | awk '$1 == "username" {print $2}')
|
|
|
|
if whiptail --yesno "$(translate "Remove Proxmox CIFS storage:")\n\n$target\n\n$(translate "Server:"): $server\n$(translate "Share:"): $share\n$(translate "Content:"): $content\n\n$(translate "WARNING: This removes the storage from Proxmox. The Samba server is not affected.")" \
|
|
16 80 --title "$(translate "Confirm Remove")"; then
|
|
|
|
show_proxmenux_logo
|
|
msg_title "$(translate "Remove CIFS Storage")"
|
|
|
|
if pvesm remove "$target" 2>/dev/null; then
|
|
msg_ok "$(translate "Storage") $target $(translate "removed successfully from Proxmox.")"
|
|
else
|
|
msg_error "$(translate "Failed to remove storage.")"
|
|
fi
|
|
|
|
echo -e ""
|
|
msg_success "$(translate "Press Enter to continue...")"
|
|
read -r
|
|
fi
|
|
;;
|
|
fstab)
|
|
local mount_path="$target"
|
|
local fstab_line
|
|
fstab_line=$(awk -v mp="$mount_path" '$2 == mp && $3 == "cifs" {print; exit}' /etc/fstab)
|
|
|
|
# Detect credentials= file for cleanup
|
|
local cred_file=""
|
|
if [[ "$fstab_line" =~ credentials=([^,[:space:]]+) ]]; then
|
|
cred_file="${BASH_REMATCH[1]}"
|
|
fi
|
|
|
|
local cred_msg
|
|
cred_msg="$(translate "(no credentials file — guest mode)")"
|
|
[[ -n "$cred_file" ]] && cred_msg="$(translate "Credentials file:") $cred_file"
|
|
|
|
if whiptail --yesno "$(translate "Remove CIFS fstab mount:")\n\n$mount_path\n\n$(translate "fstab line:")\n$fstab_line\n\n$cred_msg\n\n$(translate "Steps that will run:")\n 1. $(translate "umount the path if currently mounted")\n 2. $(translate "delete the matching line from /etc/fstab")\n 3. $(translate "delete the credentials file (if any)")\n 4. $(translate "remove the (now-empty) directory if possible")\n\n$(translate "WARNING: The Samba server is not affected. The mount directory contents are NOT deleted.")" \
|
|
22 90 --title "$(translate "Confirm Remove")"; then
|
|
|
|
show_proxmenux_logo
|
|
msg_title "$(translate "Remove CIFS fstab Mount")"
|
|
|
|
if mount | grep -q " on ${mount_path} type "; then
|
|
if umount "$mount_path" 2>/dev/null; then
|
|
msg_ok "$(translate "Unmounted:") $mount_path"
|
|
else
|
|
msg_warn "$(translate "Could not unmount") $mount_path. $(translate "The fstab entry will still be removed; reboot or manual umount needed.")"
|
|
fi
|
|
else
|
|
msg_info2 "$(translate "Not currently mounted — skipping umount.")"
|
|
fi
|
|
|
|
# Delete the matching line(s) from /etc/fstab using awk (exact $2 + $3 match).
|
|
cp /etc/fstab /etc/fstab.proxmenux.bak 2>/dev/null
|
|
if awk -v mp="$mount_path" '
|
|
$2 == mp && $3 == "cifs" { next }
|
|
{ print }
|
|
' /etc/fstab > /etc/fstab.tmp && pmx_write_file /etc/fstab < /etc/fstab.tmp; then
|
|
msg_ok "$(translate "Removed entry from /etc/fstab") ($(translate "backup at /etc/fstab.proxmenux.bak"))"
|
|
else
|
|
msg_error "$(translate "Failed to edit /etc/fstab — remove the line manually.")"
|
|
fi
|
|
|
|
systemctl daemon-reload 2>/dev/null || true
|
|
|
|
# Remove credentials file if it's under the standard ProxMenux dir
|
|
if [[ -n "$cred_file" && -f "$cred_file" && "$cred_file" == /etc/samba/credentials/* ]]; then
|
|
pmx_remove_file "$cred_file"
|
|
msg_ok "$(translate "Removed credentials file:") $cred_file"
|
|
fi
|
|
|
|
if [[ -d "$mount_path" ]] && rmdir "$mount_path" 2>/dev/null; then
|
|
msg_ok "$(translate "Removed empty mount directory:") $mount_path"
|
|
fi
|
|
|
|
echo -e ""
|
|
msg_success "$(translate "Press Enter to continue...")"
|
|
read -r
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
test_samba_connectivity() {
|
|
local FUNC_VERSION="1.0"
|
|
pmx_journal_context "test_samba_connectivity" "$FUNC_VERSION"
|
|
|
|
show_proxmenux_logo
|
|
msg_title "$(translate "Test Samba Connectivity")"
|
|
|
|
echo "=================================================="
|
|
echo ""
|
|
|
|
if which smbclient >/dev/null 2>&1; then
|
|
msg_ok "$(translate "CIFS Client Tools: AVAILABLE")"
|
|
else
|
|
msg_warn "$(translate "CIFS Client Tools: NOT AVAILABLE - installing...")"
|
|
apt-get update &>/dev/null
|
|
pmx_install_pkg cifs-utils smbclient &>/dev/null
|
|
msg_ok "$(translate "CIFS client tools installed.")"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
if command -v pvesm >/dev/null 2>&1; then
|
|
echo -e "${BOLD}$(translate "Proxmox CIFS Storage Status:")${CL}"
|
|
CIFS_STORAGES=$(pvesm status 2>/dev/null | awk '$2 == "cifs" {print $1, $3}')
|
|
|
|
if [[ -n "$CIFS_STORAGES" ]]; then
|
|
while IFS=" " read -r storage_id storage_status; do
|
|
[[ -z "$storage_id" ]] && continue
|
|
local server
|
|
server=$(get_storage_config "$storage_id" | awk '$1 == "server" {print $2}')
|
|
|
|
echo -n " [pvesm] $storage_id ($server): "
|
|
|
|
if ping -c 1 -W 2 "$server" >/dev/null 2>&1; then
|
|
echo -ne "${GN}$(translate "Reachable")${CL}"
|
|
|
|
if nc -z -w 2 "$server" 445 2>/dev/null; then
|
|
echo -e " | SMB 445: ${GN}$(translate "Open")${CL}"
|
|
elif nc -z -w 2 "$server" 139 2>/dev/null; then
|
|
echo -e " | NetBIOS 139: ${GN}$(translate "Open")${CL}"
|
|
else
|
|
echo -e " | SMB ports: ${RD}$(translate "Closed")${CL}"
|
|
fi
|
|
|
|
echo -n " $(translate "Guest access test:"): "
|
|
if smbclient -L "$server" -N >/dev/null 2>&1; then
|
|
echo -e "${GN}$(translate "Available")${CL}"
|
|
else
|
|
echo -e "${YW}$(translate "Requires authentication")${CL}"
|
|
fi
|
|
else
|
|
echo -e "${RD}$(translate "Unreachable")${CL}"
|
|
fi
|
|
|
|
if [[ "$storage_status" == "active" ]]; then
|
|
echo -e " $(translate "Proxmox status:") ${GN}$storage_status${CL}"
|
|
else
|
|
echo -e " $(translate "Proxmox status:") ${RD}$storage_status${CL}"
|
|
fi
|
|
echo ""
|
|
done <<< "$CIFS_STORAGES"
|
|
else
|
|
echo " $(translate "No CIFS Proxmox storage configured.")"
|
|
fi
|
|
else
|
|
msg_warn "$(translate "pvesm not available.")"
|
|
fi
|
|
|
|
# ---- fstab-only CIFS mounts ----
|
|
local FSTAB_ENTRIES
|
|
FSTAB_ENTRIES=$(list_cifs_fstab_entries)
|
|
echo ""
|
|
echo -e "${BOLD}$(translate "Host fstab CIFS Mounts:")${CL}"
|
|
if [[ -z "$FSTAB_ENTRIES" ]]; then
|
|
echo " $(translate "(none)")"
|
|
else
|
|
while IFS="|" read -r server share mount_path opts; do
|
|
[[ -z "$mount_path" ]] && continue
|
|
echo -n " [fstab] $mount_path ($server/$share): "
|
|
|
|
if ping -c 1 -W 2 "$server" >/dev/null 2>&1; then
|
|
echo -ne "${GN}$(translate "Reachable")${CL}"
|
|
if nc -z -w 2 "$server" 445 2>/dev/null; then
|
|
echo -e " | SMB 445: ${GN}$(translate "Open")${CL}"
|
|
elif nc -z -w 2 "$server" 139 2>/dev/null; then
|
|
echo -e " | NetBIOS 139: ${GN}$(translate "Open")${CL}"
|
|
else
|
|
echo -e " | SMB ports: ${RD}$(translate "Closed")${CL}"
|
|
fi
|
|
else
|
|
echo -e "${RD}$(translate "Unreachable")${CL}"
|
|
fi
|
|
|
|
local mstate
|
|
mstate=$(check_mount_state "$mount_path")
|
|
if [[ "$mstate" == "active" ]]; then
|
|
echo -e " $(translate "Mount status:") ${GN}$(translate "Active")${CL}"
|
|
else
|
|
echo -e " $(translate "Mount status:") ${RD}$(translate "Not currently mounted")${CL}"
|
|
fi
|
|
echo ""
|
|
done <<< "$FSTAB_ENTRIES"
|
|
fi
|
|
|
|
echo ""
|
|
msg_success "$(translate "Press Enter to continue...")"
|
|
read -r
|
|
}
|
|
|
|
# ==========================================================
|
|
# MAIN MENU
|
|
# ==========================================================
|
|
|
|
while true; do
|
|
CHOICE=$(dialog --backtitle "ProxMenux" \
|
|
--title "$(translate "Samba Host Manager - Proxmox Host")" \
|
|
--menu "$(translate "Choose an option:")" 18 70 6 \
|
|
"1" "$(translate "Mount Samba Share on Host")" \
|
|
"2" "$(translate "View CIFS Mounts (pvesm + fstab)")" \
|
|
"3" "$(translate "Remove CIFS Mount (pvesm or fstab)")" \
|
|
"4" "$(translate "Test Samba Connectivity")" \
|
|
"5" "$(translate "Exit")" \
|
|
3>&1 1>&2 2>&3)
|
|
|
|
RETVAL=$?
|
|
if [[ $RETVAL -ne 0 ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
case $CHOICE in
|
|
1) mount_cifs_share ;;
|
|
2) view_cifs_storages ;;
|
|
3) remove_cifs_storage ;;
|
|
4) test_samba_connectivity ;;
|
|
5) exit 0 ;;
|
|
*) exit 0 ;;
|
|
esac
|
|
done
|