From f37fbbfb8b544acaf8f0ed549a2a30cc05e9b7a0 Mon Sep 17 00:00:00 2001 From: MacRimi Date: Sat, 30 Aug 2025 18:56:49 +0200 Subject: [PATCH] Update menu share --- scripts/share/local-shared-manager.sh | 93 ++++++ scripts/share/lxc-mount-manager.sh | 462 ++++++++++++++++++++++++++ scripts/share/nfs_host.sh | 239 ++++++------- scripts/share/samba_host.sh | 200 +++++------ 4 files changed, 765 insertions(+), 229 deletions(-) create mode 100644 scripts/share/local-shared-manager.sh create mode 100644 scripts/share/lxc-mount-manager.sh diff --git a/scripts/share/local-shared-manager.sh b/scripts/share/local-shared-manager.sh new file mode 100644 index 0000000..da45a4d --- /dev/null +++ b/scripts/share/local-shared-manager.sh @@ -0,0 +1,93 @@ +#!/bin/bash +# ========================================================== +# ProxMenux - Local Shared Directory Manager +# ========================================================== +# Author : MacRimi +# Copyright : (c) 2024 MacRimi +# License : MIT +# Version : 1.0 +# Last Updated: $(date +%d/%m/%Y) +# ========================================================== + +# Configuration +REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main" +BASE_DIR="/usr/local/share/proxmenux" +UTILS_FILE="$BASE_DIR/utils.sh" + + +# Load utilities and shared functions +if [[ -f "$UTILS_FILE" ]]; then + source "$UTILS_FILE" +fi + +# Load common share functions +SHARE_COMMON_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main/scripts/global/share-common.func" +if ! source <(curl -s "$SHARE_COMMON_URL" 2>/dev/null); then + SHARE_COMMON_LOADED=false +else + SHARE_COMMON_LOADED=true +fi + +load_language +initialize_cache + +# ========================================================== + + + + +create_shared_directory() { + SHARED_DIR=$(pmx_select_host_mount_point "$(translate "Select Shared Directory Location")" "/mnt/shared") + [[ -z "$SHARED_DIR" ]] && return + + # Confirm overwrite if already exists + if [[ -d "$SHARED_DIR" ]]; then + if ! whiptail --yesno "$(translate "Directory already exists. Continue with permission setup?")" 10 70 --title "$(translate "Directory Exists")"; then + return + fi + fi + + # Ensure group exists + SHARE_GROUP=$(pmx_choose_or_create_group "sharedfiles") || return 1 + SHARE_GID=$(pmx_ensure_host_group "$SHARE_GROUP" 101000) || return 1 + + # --- Saneamos ACLs de /mnt para evitar herencias raras --- + if command -v setfacl >/dev/null 2>&1; then + setfacl -k /mnt 2>/dev/null || true # elimina ACL por defecto + setfacl -b /mnt 2>/dev/null || true # elimina ACL actuales + fi + chmod 755 /mnt 2>/dev/null || true + + # --- Preparamos el directorio --- + pmx_prepare_host_shared_dir "$SHARED_DIR" "$SHARE_GROUP" || return 1 + + # --- Limpiamos ACLs del directorio por si heredó algo --- + if command -v setfacl >/dev/null 2>&1; then + setfacl -b -R "$SHARED_DIR" 2>/dev/null || true + fi + + # --- Reforzamos permisos POSIX estándar --- + chown root:"$SHARE_GROUP" "$SHARED_DIR" + chmod 2775 "$SHARED_DIR" + + pmx_share_map_set "$SHARED_DIR" "$SHARE_GROUP" + + show_proxmenux_logo + msg_title "$(translate "Create Shared Directory")" + + echo -e "" + echo -e "${TAB}${BOLD}$(translate "Shared Directory Created:")${CL}" + echo -e "${TAB}${BGN}$(translate "Directory:")${CL} ${BL}$SHARED_DIR${CL}" + echo -e "${TAB}${BGN}$(translate "Group:")${CL} ${BL}$SHARE_GROUP (GID: $SHARE_GID)${CL}" + echo -e "${TAB}${BGN}$(translate "Permissions:")${CL} ${BL}2775 (rwxrwsr-x)${CL}" + echo -e "${TAB}${BGN}$(translate "Owner:")${CL} ${BL}root:$SHARE_GROUP${CL}" + echo -e "${TAB}${BGN}$(translate "ACL Status:")${CL} ${BL}$(translate "Cleaned and set for POSIX inheritance")${CL}" + echo -e "" + msg_success "$(translate "Press Enter to return to menu...")" + read -r +} + + + + +create_shared_directory diff --git a/scripts/share/lxc-mount-manager.sh b/scripts/share/lxc-mount-manager.sh new file mode 100644 index 0000000..95545e1 --- /dev/null +++ b/scripts/share/lxc-mount-manager.sh @@ -0,0 +1,462 @@ +#!/bin/bash +# ========================================================== +# ProxMenux - LXC Mount Manager (Standalone - CLEAN v1) +# ========================================================== +# Author : MacRimi +# Copyright : (c) 2024 MacRimi +# License : MIT +# Version : 3.0-clean +# Last Updated: $(date +%d/%m/%Y) +# ========================================================== + +BASE_DIR="/usr/local/share/proxmenux" +source "$BASE_DIR/utils.sh" + + +SHARE_COMMON_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main/scripts/global/share-common.func" +if ! source <(curl -s "$SHARE_COMMON_URL" 2>/dev/null); then + SHARE_COMMON_LOADED=false +else + SHARE_COMMON_LOADED=true +fi + +load_language +initialize_cache + +# ========================================================== +# CORE FUNCTIONS +# ========================================================== + + + + +ensure_host_group() { + local group_name="$1" + if ! getent group "$group_name" >/dev/null 2>&1; then + if groupadd "$group_name" >/dev/null 2>&1; then + msg_ok "$(translate "Group created:") $group_name" + else + msg_error "$(translate "Failed to create group:") $group_name" + return 1 + fi + fi + local gid + gid="$(getent group "$group_name" | cut -d: -f3)" + echo "$gid" + return 0 +} + + +get_container_uid_shift() { + local ctid="$1" + local conf="/etc/pve/lxc/${ctid}.conf" + local uid_shift + + if [[ ! -f "$conf" ]]; then + echo "100000" + return 0 + fi + + + local unpriv + unpriv=$(grep "^unprivileged:" "$conf" | awk '{print $2}') + + if [[ "$unpriv" == "1" ]]; then + + uid_shift=$(grep "^lxc.idmap" "$conf" | grep 'u 0' | awk '{print $5}' | head -1) + echo "${uid_shift:-100000}" + return 0 + fi + + echo "0" + return 0 +} + + +setup_container_access() { + local ctid="$1" group_name="$2" host_gid="$3" host_dir="$4" + local uid_shift mapped_gid + + if [[ ! "$ctid" =~ ^[0-9]+$ ]]; then + msg_error "$(translate 'Invalid container ID format:') $ctid" + return 1 + fi + + uid_shift=$(get_container_uid_shift "$ctid") + + if [[ "$uid_shift" -eq 0 ]]; then + mapped_gid="$host_gid" + msg_ok "$(translate "Privileged container - using same GID as host:") $host_gid" + else + mapped_gid=$((uid_shift + host_gid)) + msg_ok "$(translate "Unprivileged container - using mapped GID:") $mapped_gid (host GID: $host_gid, shift: $uid_shift)" + fi + + + pct exec "$ctid" -- sh -c " + if ! getent group $group_name >/dev/null 2>&1; then + groupadd -g $mapped_gid $group_name 2>/dev/null || true + else + ct_gid=\$(getent group $group_name | cut -d: -f3) + if [ \"\$ct_gid\" != \"$mapped_gid\" ]; then + groupdel $group_name 2>/dev/null || true + groupadd -g $mapped_gid $group_name 2>/dev/null || true + fi + fi + + + getent passwd | while IFS=: read -r username _ uid gid _ home _; do + if [ \"\$uid\" -eq 0 ] || [ \"\$uid\" -ge 1000 ] || [ \"\$username\" = \"nobody\" ] || [ \"\$username\" = \"www-data\" ]; then + usermod -aG $group_name \"\$username\" 2>/dev/null || true + fi + done + " 2>/dev/null + + + if command -v setfacl >/dev/null 2>&1; then + pct exec "$ctid" -- getent passwd | awk -F: '{print $1, $3}' | while read user uid; do + [[ "$uid" -eq 0 ]] && continue + host_uid=$((uid_shift + uid)) + setfacl -m u:$host_uid:rwx "$host_dir" 2>/dev/null || true + done + msg_ok "$(translate "ACL permissions applied for container users")" + fi + + + chmod 2775 "$host_dir" 2>/dev/null || true + chgrp "$group_name" "$host_dir" 2>/dev/null || true + + msg_ok "$(translate "Group mapping ensured:") host=$host_gid → ct=$mapped_gid" + msg_ok "$(translate "Multi-approach access configuration completed")" + + return 0 +} + + + + + +get_next_mp_index() { + local ctid="$1" + local conf="/etc/pve/lxc/${ctid}.conf" + + if [[ ! "$ctid" =~ ^[0-9]+$ ]] || [[ ! -f "$conf" ]]; then + echo "0" + return 0 + fi + + local used idx next=0 + used=$(awk -F: '/^mp[0-9]+:/ {print $1}' "$conf" | sed 's/mp//' | sort -n) + for idx in $used; do + [[ "$idx" -ge "$next" ]] && next=$((idx+1)) + done + echo "$next" +} + + +add_bind_mount() { + local ctid="$1" host_path="$2" ct_path="$3" + local mpidx result + + if [[ ! "$ctid" =~ ^[0-9]+$ ]]; then + msg_error "$(translate 'Invalid container ID format:') $ctid" + return 1 + fi + + if [[ -z "$ctid" || -z "$host_path" || -z "$ct_path" ]]; then + msg_error "$(translate "Missing arguments")" + return 1 + fi + + + if pct config "$ctid" | grep -q "$host_path"; then + echo -e + msg_warn "$(translate "Directory already mounted in container configuration.")" + echo -e "" + msg_success "$(translate 'Press Enter to return to menu...')" + read -r + return 1 + fi + + mpidx=$(get_next_mp_index "$ctid") + + result=$(pct set "$ctid" -mp${mpidx} "$host_path,mp=$ct_path,backup=0,ro=0,acl=1" 2>&1) + + if [[ $? -eq 0 ]]; then + msg_ok "$(translate "Successfully mounted:") $host_path → $ct_path" + return 0 + else + msg_error "$(translate "Error mounting folder:") $result" + return 1 + fi +} + + +# ========================================================== + + +select_lxc_container() { + local ct_list ctid ct_status + + ct_list=$(pct list | awk 'NR>1 {print $1, $2, $3}') + if [[ -z "$ct_list" ]]; then + dialog --title "$(translate "Error")" \ + --msgbox "$(translate "No LXC containers available")" 8 50 + return 1 + fi + + local options=() + while read -r id name status; do + if [[ -n "$id" ]]; then + options+=("$id" "$name ($status)") + fi + done <<< "$ct_list" + + ctid=$(dialog --title "$(translate "Select LXC Container")" \ + --menu "$(translate "Select container:")" 20 70 12 \ + "${options[@]}" 3>&1 1>&2 2>&3) + + if [[ -z "$ctid" ]]; then + return 1 + fi + + echo "$ctid" + return 0 +} + + +select_container_mount_point() { + local ctid="$1" + local host_dir="$2" + local choice mount_point existing_dirs options + + while true; do + choice=$(whiptail --title "$(translate "Container Mount Point")" \ + --menu "$(translate "Where to mount inside container?")" 18 70 5 \ + "1" "$(translate "Create new directory in /mnt")" \ + "2" "$(translate "Use existing directory in /mnt")" \ + "3" "$(translate "Enter path manually")" \ + "4" "$(translate "Cancel")" 3>&1 1>&2 2>&3) || return 1 + + case "$choice" in + 1) + mount_point=$(whiptail --inputbox "$(translate "Enter folder name for /mnt:")" 10 60 "shared" 3>&1 1>&2 2>&3) || continue + [[ -z "$mount_point" ]] && continue + mount_point="/mnt/$mount_point" + pct exec "$ctid" -- mkdir -p "$mount_point" 2>/dev/null + ;; + + 2) + existing_dirs=$(pct exec "$ctid" -- ls -1 /mnt 2>/dev/null | awk '{print "/mnt/"$1" "$1}') + if [[ -z "$existing_dirs" ]]; then + whiptail --msgbox "$(translate "No existing directories found in /mnt")" 8 60 + continue + fi + mount_point=$(whiptail --title "$(translate "Select Existing Folder")" \ + --menu "$(translate "Choose a folder from /mnt:")" 20 70 10 \ + $existing_dirs 3>&1 1>&2 2>&3) || continue + ;; + + 3) + mount_point=$(whiptail --inputbox "$(translate "Enter full path:")" 10 70 "/mnt/shared" 3>&1 1>&2 2>&3) || continue + [[ -z "$mount_point" ]] && continue + pct exec "$ctid" -- mkdir -p "$mount_point" 2>/dev/null + ;; + + 4) + return 1 + ;; + esac + + if pct exec "$ctid" -- test -d "$mount_point" 2>/dev/null; then + echo "$mount_point" + return 0 + else + whiptail --msgbox "$(translate "Could not create or access directory:") $mount_point" 8 70 + continue + fi + done +} + + + +mount_host_directory_to_lxc() { + + # Step 1: Select container + local container_id + container_id=$(select_lxc_container) + if [[ $? -ne 0 || -z "$container_id" ]]; then + return 1 + fi + + show_proxmenux_logo + msg_title "$(translate 'Mount Host Directory to LXC Container')" + + # Step 1.1: Ensure running + ct_status=$(pct status "$container_id" | awk '{print $2}') + if [[ "$ct_status" != "running" ]]; then + msg_info "$(translate "Starting container") $container_id..." + if pct start "$container_id"; then + sleep 3 + msg_ok "$(translate "Container started")" + else + msg_error "$(translate "Failed to start container")" + return 1 + fi + fi + msg_ok "$(translate 'Select LXC container')" + + + + # Step 2: Select host directory + local host_dir + host_dir=$(select_host_directory) + if [[ -z "$host_dir" ]]; then + return 1 + fi + msg_ok "$(translate 'Select Host directory')" + + # Step 3: Setup group + local group_name="sharedfiles" + local group_gid + group_gid=$(ensure_host_group "$group_name") + if [[ -z "$group_gid" ]]; then + return 1 + fi + + # Set basic permissions + chown -R root:"$group_name" "$host_dir" 2>/dev/null || true + chmod -R 2775 "$host_dir" 2>/dev/null || true + + msg_ok "$(translate 'Select container mount point')" + + # Step 4: Select container mount point + local ct_mount_point + ct_mount_point=$(select_container_mount_point "$container_id" "$host_dir") + if [[ -z "$ct_mount_point" ]]; then + return 1 + fi + + # Step 5: Confirmation + local uid_shift container_type + uid_shift=$(get_container_uid_shift "$container_id") + if [[ "$uid_shift" -eq 0 ]]; then + container_type="$(translate 'Privileged')" + else + container_type="$(translate 'Unprivileged')" + fi + + local confirm_msg="$(translate "Mount Configuration:") + +$(translate "Container ID:"): $container_id ($container_type) +$(translate "Host Directory:"): $host_dir +$(translate "Container Mount Point:"): $ct_mount_point +$(translate "Shared Group:"): $group_name (GID: $group_gid) + +$(translate "Proceed?")" + + if ! whiptail --title "$(translate "Confirm Mount")" --yesno "$confirm_msg" 16 70; then + return 1 + fi + + # Step 6: Add mount + if ! add_bind_mount "$container_id" "$host_dir" "$ct_mount_point"; then + return 1 + fi + + + + + + # Step 7: Setup access ====================================================== + + setup_container_access "$container_id" "$group_name" "$group_gid" "$host_dir" + + # =========================================================================== + + + + + # Step 8: Final setup + pct exec "$container_id" -- chgrp "$group_name" "$ct_mount_point" 2>/dev/null || true + pct exec "$container_id" -- chmod 2775 "$ct_mount_point" 2>/dev/null || true + + # Step 9: Summary + echo -e "" + echo -e "${TAB}${BOLD}$(translate 'Mount Added Successfully:')${CL}" + echo -e "${TAB}${BGN}$(translate 'Container:')${CL} ${BL}$container_id ($container_type)${CL}" + echo -e "${TAB}${BGN}$(translate 'Host Directory:')${CL} ${BL}$host_dir${CL}" + echo -e "${TAB}${BGN}$(translate 'Mount Point:')${CL} ${BL}$ct_mount_point${CL}" + echo -e "${TAB}${BGN}$(translate 'Group:')${CL} ${BL}$group_name (GID: $group_gid)${CL}" + + + echo -e "" + if whiptail --yesno "$(translate "Restart container to activate mount?")" 8 60; then + msg_info "$(translate 'Restarting container...')" + if pct reboot "$container_id"; then + sleep 5 + msg_ok "$(translate 'Container restarted successfully')" + + echo -e + echo -e "${TAB}${BOLD}$(translate 'Testing access and read/write:')${CL}" + test_user=$(pct exec "$container_id" -- sh -c "id -u ncp >/dev/null 2>&1 && echo ncp || echo www-data") + + if pct exec "$container_id" -- su -s /bin/bash $test_user -c "touch $ct_mount_point/test_access.txt" 2>/dev/null; then + msg_ok "$(translate "Mount access and read/write successful (tested as $test_user)")" + rm -f "$host_dir/test_access.txt" 2>/dev/null || true + else + msg_warn "$(translate "⚠ Access test failed - check permissions (user: $test_user)")" + fi + + else + msg_warn "$(translate 'Failed to restart - restart manually')" + fi + fi + + echo -e "" + msg_success "$(translate 'Press Enter to continue...')" + read -r +} + +# ========================================================== +# MAIN MENU +# ========================================================== + +main_menu() { + while true; do + choice=$(dialog --title "$(translate 'LXC Mount Manager')" \ + --menu "$(translate 'Choose an option:')" 16 60 4 \ + "1" "$(translate 'Mount Host Directory to LXC')" \ + "2" "$(translate 'View Mount Points')" \ + "3" "$(translate 'Remove Mount Point')" \ + "4" "$(translate 'Exit')" 3>&1 1>&2 2>&3) + + case $choice in + 1) + mount_host_directory_to_lxc + ;; + 2) + msg_info2 "$(translate 'Feature coming soon...')" + read -p "$(translate 'Press Enter to continue...')" + ;; + 3) + msg_info2 "$(translate 'Feature coming soon...')" + read -p "$(translate 'Press Enter to continue...')" + ;; + 4|"") + exit 0 + ;; + esac + done +} + +# ========================================================== +# MAIN EXECUTION +# ========================================================== + +if ! command -v pct >/dev/null 2>&1; then + echo "Error: This script must be run on a Proxmox host with LXC support." + exit 1 +fi + +main_menu diff --git a/scripts/share/nfs_host.sh b/scripts/share/nfs_host.sh index cc3f794..1598b35 100644 --- a/scripts/share/nfs_host.sh +++ b/scripts/share/nfs_host.sh @@ -25,28 +25,31 @@ fi load_language initialize_cache +# Load common share functions +SHARE_COMMON_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main/scripts/global/share-common.func" +if ! source <(curl -s "$SHARE_COMMON_URL" 2>/dev/null); then + msg_warn "$(translate "Could not load shared functions. Using fallback methods.")" + SHARE_COMMON_LOADED=false +else + SHARE_COMMON_LOADED=true +fi 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 - discover_nfs_servers() { show_proxmenux_logo msg_title "$(translate "NFS Host Manager - Proxmox Host")" msg_info "$(translate "Scanning network for NFS servers...")" - - HOST_IP=$(hostname -I | awk '{print $1}') NETWORK=$(echo "$HOST_IP" | cut -d. -f1-3).0/24 - if ! which nmap >/dev/null 2>&1; then apt-get install -y nmap &>/dev/null fi - SERVERS=$(nmap -p 2049 --open "$NETWORK" 2>/dev/null | grep -B 4 "2049/tcp open" | grep "Nmap scan report" | awk '{print $5}' | sort -u || true) @@ -120,7 +123,6 @@ select_nfs_export() { 10 60 return 1 fi - if ! ping -c 1 -W 3 "$NFS_SERVER" >/dev/null 2>&1; then whiptail --title "$(translate "Connection Error")" \ @@ -128,7 +130,6 @@ select_nfs_export() { 12 70 return 1 fi - if ! nc -z -w 3 "$NFS_SERVER" 2049 2>/dev/null; then whiptail --title "$(translate "NFS Port Error")" \ @@ -136,7 +137,6 @@ select_nfs_export() { 12 70 return 1 fi - EXPORTS_OUTPUT=$(showmount -e "$NFS_SERVER" 2>&1) EXPORTS_RESULT=$? @@ -194,55 +194,23 @@ select_nfs_export() { [[ -n "$NFS_EXPORT" ]] && return 0 || return 1 } + + + + + select_host_mount_point() { - while true; do - METHOD=$(whiptail --title "$(translate "Select Mount Point")" --menu "$(translate "Where do you want to mount the NFS export on the host?")" 15 70 4 \ - "mnt" "$(translate "Create folder in /mnt")" \ - "media" "$(translate "Create folder in /media")" \ - "srv" "$(translate "Create folder in /srv")" \ - "custom" "$(translate "Enter custom path")" 3>&1 1>&2 2>&3) - - case "$METHOD" in - mnt) - EXPORT_NAME=$(basename "$NFS_EXPORT") - DEFAULT_NAME="${EXPORT_NAME}" - FOLDER_NAME=$(whiptail --inputbox "$(translate "Enter folder name for /mnt:")" 10 60 "$DEFAULT_NAME" --title "$(translate "Folder in /mnt")" 3>&1 1>&2 2>&3) - if [[ -n "$FOLDER_NAME" ]]; then - MOUNT_POINT="/mnt/$FOLDER_NAME" - return 0 - fi - ;; - media) - EXPORT_NAME=$(basename "$NFS_EXPORT") - DEFAULT_NAME="nfs_${NFS_SERVER}_${EXPORT_NAME}" - FOLDER_NAME=$(whiptail --inputbox "$(translate "Enter folder name for /media:")" 10 60 "$DEFAULT_NAME" --title "$(translate "Folder in /media")" 3>&1 1>&2 2>&3) - if [[ -n "$FOLDER_NAME" ]]; then - MOUNT_POINT="/media/$FOLDER_NAME" - return 0 - fi - ;; - srv) - EXPORT_NAME=$(basename "$NFS_EXPORT") - DEFAULT_NAME="nfs_${NFS_SERVER}_${EXPORT_NAME}" - FOLDER_NAME=$(whiptail --inputbox "$(translate "Enter folder name for /srv:")" 10 60 "$DEFAULT_NAME" --title "$(translate "Folder in /srv")" 3>&1 1>&2 2>&3) - if [[ -n "$FOLDER_NAME" ]]; then - MOUNT_POINT="/srv/$FOLDER_NAME" - return 0 - fi - ;; - custom) - MOUNT_POINT=$(whiptail --inputbox "$(translate "Enter full path for mount point:")" 10 70 "/mnt/nfs_share" --title "$(translate "Custom Path")" 3>&1 1>&2 2>&3) - if [[ -n "$MOUNT_POINT" ]]; then - return 0 - fi - ;; - *) - return 1 - ;; - esac - done + local export_name=$(basename "$NFS_EXPORT") + local default_path="/mnt/shared_nfs_${export_name}" + + MOUNT_POINT=$(pmx_select_host_mount_point "$(translate "NFS Mount Point")" "$default_path") + [[ -n "$MOUNT_POINT" ]] && return 0 || return 1 } + + + + configure_host_mount_options() { MOUNT_TYPE=$(whiptail --title "$(translate "Mount Options")" --menu "$(translate "Select mount configuration:")" 15 70 4 \ "default" "$(translate "Default options")" \ @@ -271,7 +239,6 @@ configure_host_mount_options() { MOUNT_OPTIONS="rw,hard,intr,rsize=8192,wsize=8192,timeo=14" ;; esac - if whiptail --yesno "$(translate "Do you want to make this mount permanent?")\n\n$(translate "This will add the mount to /etc/fstab so it persists after reboot.")" 10 70 --title "$(translate "Permanent Mount")"; then PERMANENT_MOUNT=true @@ -282,33 +249,55 @@ configure_host_mount_options() { return 1 fi fi + + # Test basic NFS connectivity before offering Proxmox storage + show_proxmenux_logo + msg_info "$(translate "Testing NFS export accessibility...")" - - if whiptail --yesno "$(translate "Do you want to add this as Proxmox storage?")\n\n$(translate "This will make the NFS share available as storage in Proxmox web interface.")" 10 70 --title "$(translate "Proxmox Storage")"; then - PROXMOX_STORAGE=true + # Try a simple mount test to validate the export + TEMP_MOUNT="/tmp/nfs_test_$$" + mkdir -p "$TEMP_MOUNT" 2>/dev/null + + NFS_PATH="$NFS_SERVER:$NFS_EXPORT" + if timeout 10 mount -t nfs -o ro,soft,timeo=5 "$NFS_PATH" "$TEMP_MOUNT" 2>/dev/null; then + umount "$TEMP_MOUNT" 2>/dev/null || true + rmdir "$TEMP_MOUNT" 2>/dev/null || true + msg_ok "$(translate "NFS export is accessible")" - - STORAGE_ID=$(whiptail --inputbox "$(translate "Enter storage ID for Proxmox:")" 10 60 "nfs-$(echo $NFS_SERVER | tr '.' '-')" --title "$(translate "Storage ID")" 3>&1 1>&2 2>&3) - STORAGE_ID_RESULT=$? - - if [[ $STORAGE_ID_RESULT -ne 0 ]]; then - - if whiptail --yesno "$(translate "Storage ID input was cancelled.")\n\n$(translate "Do you want to continue without Proxmox storage integration?")" 10 70 --title "$(translate "Continue Without Storage")"; then + # Export is accessible, offer Proxmox storage integration + if whiptail --yesno "$(translate "Do you want to add this as Proxmox storage?")\n\n$(translate "This will make the NFS share available as storage in Proxmox web interface.")" 10 70 --title "$(translate "Proxmox Storage")"; then + PROXMOX_STORAGE=true + + STORAGE_ID=$(whiptail --inputbox "$(translate "Enter storage ID for Proxmox:")" 10 60 "nfs-$(echo $NFS_SERVER | tr '.' '-')" --title "$(translate "Storage ID")" 3>&1 1>&2 2>&3) + STORAGE_ID_RESULT=$? + + if [[ $STORAGE_ID_RESULT -ne 0 ]]; then + if whiptail --yesno "$(translate "Storage ID input was cancelled.")\n\n$(translate "Do you want to continue without Proxmox storage integration?")" 10 70 --title "$(translate "Continue Without Storage")"; then + PROXMOX_STORAGE=false + else + return 1 + fi + else + [[ -z "$STORAGE_ID" ]] && STORAGE_ID="nfs-$(echo $NFS_SERVER | tr '.' '-')" + fi + else + DIALOG_RESULT=$? + if [[ $DIALOG_RESULT -eq 1 ]]; then PROXMOX_STORAGE=false else return 1 fi - else - - [[ -z "$STORAGE_ID" ]] && STORAGE_ID="nfs-$(echo $NFS_SERVER | tr '.' '-')" fi else - DIALOG_RESULT=$? - if [[ $DIALOG_RESULT -eq 1 ]]; then - + # Export is not accessible or has issues + rmdir "$TEMP_MOUNT" 2>/dev/null || true + msg_warn "$(translate "NFS export accessibility test failed")" + + if whiptail --yesno "$(translate "The NFS export could not be validated for accessibility.")\n\n$(translate "This might be due to:")\n• $(translate "Network connectivity issues")\n• $(translate "Export permission restrictions")\n• $(translate "Firewall blocking access")\n\n$(translate "Do you want to continue mounting anyway?")\n$(translate "(Proxmox storage integration will be skipped)")" 16 80 --title "$(translate "Export Validation Failed")"; then PROXMOX_STORAGE=false + msg_info "$(translate "Continuing without Proxmox storage integration due to accessibility issues.")" + sleep 2 else - return 1 fi fi @@ -348,7 +337,6 @@ add_proxmox_nfs_storage() { 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" @@ -359,18 +347,12 @@ add_proxmox_nfs_storage() { fi msg_ok "$(translate "Storage ID is available")" - msg_info "$(translate "Creating NFS storage...")" CONTENT_LIST="backup,iso,vztmpl" - - -############################################# + # Use NFS version 3 for better compatibility NFS_VERSION="3" - -############################################# - PVESM_OUTPUT=$(pvesm add nfs "$storage_id" \ --server "$server" \ @@ -401,8 +383,40 @@ add_proxmox_nfs_storage() { fi } -mount_host_nfs_share() { +prepare_host_directory() { + local mount_point="$1" + + if [[ "$SHARE_COMMON_LOADED" == "true" ]]; then + # Use common functions for advanced directory preparation + local group_name + group_name=$(pmx_choose_or_create_group "sharedfiles") + if [[ -n "$group_name" ]]; then + local host_gid + host_gid=$(pmx_ensure_host_group "$group_name") + if [[ -n "$host_gid" ]]; then + pmx_prepare_host_shared_dir "$mount_point" "$group_name" + pmx_share_map_set "$mount_point" "$group_name" + msg_ok "$(translate "Directory prepared with shared group:") $group_name (GID: $host_gid)" + return 0 + fi + fi + msg_warn "$(translate "Failed to use shared functions, using basic directory creation.")" + fi + + # Fallback: basic directory creation + if ! test -d "$mount_point"; then + if mkdir -p "$mount_point"; then + msg_ok "$(translate "Mount point created on host.")" + return 0 + else + msg_error "$(translate "Failed to create mount point on host.")" + return 1 + fi + fi + return 0 +} +mount_host_nfs_share() { if ! which showmount >/dev/null 2>&1; then msg_error "$(translate "NFS client tools not found. Please check Proxmox installation.")" return 1 @@ -428,25 +442,11 @@ mount_host_nfs_share() { # Step 4: configure_host_mount_options || return - - - # =================================================== show_proxmenux_logo msg_title "$(translate "Mount NFS Share on Host")" - -# ===================================================== - - if ! test -d "$MOUNT_POINT"; then - if mkdir -p "$MOUNT_POINT"; then - msg_ok "$(translate "Mount point created on host.")" - else - msg_error "$(translate "Failed to create mount point on host.")" - return 1 - fi - fi - + prepare_host_directory "$MOUNT_POINT" || return 1 if mount | grep -q "$MOUNT_POINT"; then msg_warn "$(translate "Something is already mounted at") $MOUNT_POINT" @@ -455,25 +455,20 @@ mount_host_nfs_share() { fi umount "$MOUNT_POINT" 2>/dev/null || true fi - NFS_PATH="$NFS_SERVER:$NFS_EXPORT" if mount -t nfs -o "$MOUNT_OPTIONS" "$NFS_PATH" "$MOUNT_POINT" > /dev/null 2>&1; then msg_ok "$(translate "NFS share mounted successfully on host!")" - - if touch "$MOUNT_POINT/.test_write" 2>/dev/null; then rm "$MOUNT_POINT/.test_write" 2>/dev/null msg_ok "$(translate "Write access confirmed.")" else msg_warn "$(translate "Read-only access (or no write permissions).")" fi - if [[ "$PERMANENT_MOUNT" == "true" ]]; then - sed -i "\|$MOUNT_POINT|d" /etc/fstab FSTAB_ENTRY="$NFS_PATH $MOUNT_POINT nfs $MOUNT_OPTIONS 0 0" echo "$FSTAB_ENTRY" >> /etc/fstab @@ -483,12 +478,10 @@ mount_host_nfs_share() { systemctl daemon-reload 2>/dev/null || true msg_ok "$(translate "Systemd configuration reloaded.")" fi - if [[ "$PROXMOX_STORAGE" == "true" ]]; then add_proxmox_nfs_storage "$STORAGE_ID" "$NFS_SERVER" "$NFS_EXPORT" "$MOUNT_POINT" fi - echo -e "" echo -e "${TAB}${BOLD}$(translate "Host Mount Information:")${CL}" @@ -565,7 +558,6 @@ view_host_nfs_mounts() { else echo "$(translate "No permanent NFS mounts configured on host.")" fi - echo -e "${BOLD}$(translate "Proxmox NFS Storage:")${CL}" if which pvesm >/dev/null 2>&1; then @@ -574,7 +566,6 @@ view_host_nfs_mounts() { while IFS= read -r storage_id; do if [[ -n "$storage_id" ]]; then echo -e "${TAB}${BGN}$(translate "Storage ID:")${CL} ${BL}$storage_id${CL}" - STORAGE_INFO=$(pvesm config "$storage_id" 2>/dev/null || true) if [[ -n "$STORAGE_INFO" ]]; then @@ -602,10 +593,8 @@ view_host_nfs_mounts() { } unmount_host_nfs_share() { - MOUNTS=$(mount | grep -E "type nfs|:.*on.*nfs" | awk '{print $3}' | sort -u || true) FSTAB_MOUNTS=$(grep -E "nfs" /etc/fstab 2>/dev/null | grep -v "^#" | awk '{print $2}' | sort -u || true) - ALL_MOUNTS=$(echo -e "$MOUNTS\n$FSTAB_MOUNTS" | sort -u | grep -v "^$" || true) @@ -617,7 +606,6 @@ unmount_host_nfs_share() { OPTIONS=() while IFS= read -r mount_point; do if [[ -n "$mount_point" ]]; then - NFS_PATH=$(mount | grep "$mount_point" | awk '{print $1}' || grep "$mount_point" /etc/fstab | awk '{print $1}' || echo "Unknown") SERVER=$(echo "$NFS_PATH" | cut -d: -f1) EXPORT=$(echo "$NFS_PATH" | cut -d: -f2) @@ -627,16 +615,13 @@ unmount_host_nfs_share() { SELECTED_MOUNT=$(dialog --backtitle "ProxMenux" --title "$(translate "Unmount NFS Share")" --menu "$(translate "Select mount point to unmount:")" 20 80 10 "${OPTIONS[@]}" 3>&1 1>&2 2>&3) [[ -z "$SELECTED_MOUNT" ]] && return - NFS_PATH=$(mount | grep "$SELECTED_MOUNT" | awk '{print $1}' || grep "$SELECTED_MOUNT" /etc/fstab | awk '{print $1}' || echo "Unknown") SERVER=$(echo "$NFS_PATH" | cut -d: -f1) EXPORT=$(echo "$NFS_PATH" | cut -d: -f2) - PROXMOX_STORAGE="" if which pvesm >/dev/null 2>&1; then - NFS_STORAGES=$(pvesm status 2>/dev/null | grep "nfs" | awk '{print $1}' || true) while IFS= read -r storage_id; do if [[ -n "$storage_id" ]]; then @@ -650,7 +635,6 @@ unmount_host_nfs_share() { fi done <<< "$NFS_STORAGES" fi - CONFIRMATION_MSG="$(translate "Are you sure you want to unmount this NFS share?")\n\n$(translate "Mount Point:"): $SELECTED_MOUNT\n$(translate "Server:"): $SERVER\n$(translate "Export:"): $EXPORT\n\n$(translate "This will:")\n• $(translate "Unmount the NFS share")\n• $(translate "Remove from /etc/fstab")" @@ -671,7 +655,6 @@ unmount_host_nfs_share() { msg_warn "$(translate "Failed to remove Proxmox storage, continuing with unmount...")" fi fi - if mount | grep -q "$SELECTED_MOUNT"; then if umount "$SELECTED_MOUNT"; then @@ -686,7 +669,6 @@ unmount_host_nfs_share() { fi fi fi - msg_info "$(translate "Removing from /etc/fstab...")" sed -i "\|[[:space:]]$SELECTED_MOUNT[[:space:]]|d" /etc/fstab @@ -707,9 +689,6 @@ unmount_host_nfs_share() { read -r } - - - manage_proxmox_storage() { if ! command -v pvesm >/dev/null 2>&1; then dialog --backtitle "ProxMenux" --title "$(translate "Error")" --msgbox "\n$(translate "pvesm command not found. This should not happen on Proxmox.")" 8 60 @@ -722,7 +701,6 @@ manage_proxmox_storage() { return fi - OPTIONS=() while IFS= read -r storage_id; do if [[ -n "$storage_id" ]]; then @@ -741,13 +719,11 @@ manage_proxmox_storage() { SELECTED_STORAGE=$(dialog --backtitle "ProxMenux" --title "$(translate "Manage Proxmox NFS Storage")" --menu "$(translate "Select storage to manage:")" 20 80 10 "${OPTIONS[@]}" 3>&1 1>&2 2>&3) [[ -z "$SELECTED_STORAGE" ]] && return - STORAGE_INFO=$(pvesm config "$SELECTED_STORAGE" 2>/dev/null || true) SERVER=$(echo "$STORAGE_INFO" | grep "server" | awk '{print $2}') EXPORT=$(echo "$STORAGE_INFO" | grep "export" | awk '{print $2}') CONTENT=$(echo "$STORAGE_INFO" | grep "content" | awk '{print $2}') - FSTAB_NFS=$(grep "nfs" /etc/fstab 2>/dev/null || true) if [[ -n "$FSTAB_NFS" ]]; then while IFS= read -r fstab_line; do @@ -762,7 +738,6 @@ manage_proxmox_storage() { done <<< "$FSTAB_NFS" fi - if whiptail --yesno "$(translate "Are you sure you want to REMOVE storage") $SELECTED_STORAGE?\n\n$(translate "Server:"): $SERVER\n$(translate "Export:"): $EXPORT\n\n$(translate "WARNING: This will permanently remove the storage from Proxmox configuration.")\n$(translate "The NFS mount on the host will NOT be affected.")" 14 80 --title "$(translate "Remove Storage")"; then show_proxmenux_logo msg_title "$(translate "Remove Storage")" @@ -776,23 +751,17 @@ manage_proxmox_storage() { msg_error "$(translate "Failed to remove storage.")" fi fi - - } - - test_host_nfs_connectivity() { show_proxmenux_logo msg_title "$(translate "Test NFS Connectivity on Host")" echo -e "$(translate "NFS Client Status on Proxmox Host:"):" echo "==================================" - if which showmount >/dev/null 2>&1; then echo "$(translate "NFS Client Tools: AVAILABLE")" - if systemctl is-active --quiet rpcbind 2>/dev/null; then echo "$(translate "RPC Bind Service: RUNNING")" @@ -813,7 +782,6 @@ test_host_nfs_connectivity() { echo "" echo "$(translate "Testing network connectivity...")" - FSTAB_SERVERS=$(grep "nfs" /etc/fstab 2>/dev/null | awk '{print $1}' | cut -d: -f1 | sort -u || true) if [[ -n "$FSTAB_SERVERS" ]]; then @@ -822,7 +790,6 @@ test_host_nfs_connectivity() { echo -n "$(translate "Testing") $server: " if ping -c 1 -W 2 "$server" >/dev/null 2>&1; then echo -e "${GN}$(translate "Reachable")${CL}" - echo -n " $(translate "NFS port 2049"): " if nc -z -w 2 "$server" 2049 2>/dev/null; then @@ -830,7 +797,6 @@ test_host_nfs_connectivity() { else echo -e "${RD}$(translate "Closed")${CL}" fi - echo -n " $(translate "Export list test"): " if showmount -e "$server" >/dev/null 2>&1; then @@ -846,7 +812,6 @@ test_host_nfs_connectivity() { else echo "$(translate "No NFS servers configured to test.")" fi - echo "" echo "$(translate "Proxmox NFS Storage Status:")" @@ -866,6 +831,18 @@ test_host_nfs_connectivity() { echo "" echo "$(translate "This is unusual for Proxmox. NFS client tools should be installed.")" fi + + echo "" + echo "$(translate "ProxMenux Extensions:")" + if [[ "$SHARE_COMMON_LOADED" == "true" ]]; then + echo "$(translate "Shared Functions: LOADED")" + if [[ -f "$PROXMENUX_SHARE_MAP_DB" ]]; then + MAPPED_DIRS=$(wc -l < "$PROXMENUX_SHARE_MAP_DB" 2>/dev/null || echo "0") + echo "$(translate "Mapped directories:"): $MAPPED_DIRS" + fi + else + echo "$(translate "Shared Functions: NOT LOADED (using fallback methods)")" + fi echo "" msg_success "$(translate "Press Enter to return to menu...")" diff --git a/scripts/share/samba_host.sh b/scripts/share/samba_host.sh index 4b8bba8..462e678 100644 --- a/scripts/share/samba_host.sh +++ b/scripts/share/samba_host.sh @@ -16,7 +16,6 @@ REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main" BASE_DIR="/usr/local/share/proxmenux" UTILS_FILE="$BASE_DIR/utils.sh" -VENV_PATH="/opt/googletrans-env" CREDENTIALS_DIR="/etc/samba/credentials" if [[ -f "$UTILS_FILE" ]]; then @@ -26,6 +25,15 @@ fi load_language initialize_cache +# Load common share functions +SHARE_COMMON_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main/scripts/global/share-common.func" +if ! source <(curl -s "$SHARE_COMMON_URL" 2>/dev/null); then + msg_warn "$(translate "Could not load shared functions. Using fallback methods.")" + SHARE_COMMON_LOADED=false +else + SHARE_COMMON_LOADED=true +fi + 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 @@ -499,78 +507,43 @@ EOF [[ -n "$SAMBA_SHARE" ]] && return 0 || return 1 } + + + + + select_host_mount_point() { - while true; do - METHOD=$(whiptail --title "$(translate "Select Mount Point")" --menu "$(translate "Where do you want to mount the Samba share on the host?")" 15 70 4 \ - "mnt" "$(translate "Create folder in /mnt")" \ - "media" "$(translate "Create folder in /media")" \ - "srv" "$(translate "Create folder in /srv")" \ - "custom" "$(translate "Enter custom path")" 3>&1 1>&2 2>&3) - - case "$METHOD" in - mnt) - DEFAULT_NAME="${SAMBA_SHARE}" - FOLDER_NAME=$(whiptail --inputbox "$(translate "Enter folder name for /mnt:")" 10 60 "$DEFAULT_NAME" --title "$(translate "Folder in /mnt")" 3>&1 1>&2 2>&3) - if [[ -n "$FOLDER_NAME" ]]; then - MOUNT_POINT="/mnt/$FOLDER_NAME" - return 0 - fi - ;; - media) - DEFAULT_NAME="samba_${SAMBA_SERVER}_${SAMBA_SHARE}" - FOLDER_NAME=$(whiptail --inputbox "$(translate "Enter folder name for /media:")" 10 60 "$DEFAULT_NAME" --title "$(translate "Folder in /media")" 3>&1 1>&2 2>&3) - if [[ -n "$FOLDER_NAME" ]]; then - MOUNT_POINT="/media/$FOLDER_NAME" - return 0 - fi - ;; - srv) - DEFAULT_NAME="samba_${SAMBA_SERVER}_${SAMBA_SHARE}" - FOLDER_NAME=$(whiptail --inputbox "$(translate "Enter folder name for /srv:")" 10 60 "$DEFAULT_NAME" --title "$(translate "Folder in /srv")" 3>&1 1>&2 2>&3) - if [[ -n "$FOLDER_NAME" ]]; then - MOUNT_POINT="/srv/$FOLDER_NAME" - return 0 - fi - ;; - custom) - MOUNT_POINT=$(whiptail --inputbox "$(translate "Enter full path for mount point:")" 10 70 "/mnt/samba_share" --title "$(translate "Custom Path")" 3>&1 1>&2 2>&3) - if [[ -n "$MOUNT_POINT" ]]; then - return 0 - fi - ;; - *) - return 1 - ;; - esac - done + local default_path="/mnt/shared_samba_${SAMBA_SHARE}" + + MOUNT_POINT=$(pmx_select_host_mount_point "$(translate "Samba Mount Point")" "$default_path") + [[ -n "$MOUNT_POINT" ]] && return 0 || return 1 } + + + configure_host_mount_options() { MOUNT_TYPE=$(whiptail --title "$(translate "Mount Options")" --menu "$(translate "Select mount configuration:")" 15 70 4 \ "default" "$(translate "Default options")" \ "readonly" "$(translate "Read-only mount")" \ - "performance" "$(translate "Performance optimized")" \ "custom" "$(translate "Custom options")" 3>&1 1>&2 2>&3) [[ $? -ne 0 ]] && return 1 case "$MOUNT_TYPE" in default) - MOUNT_OPTIONS="rw,file_mode=0664,dir_mode=0775,iocharset=utf8" + MOUNT_OPTIONS="rw,noperm,file_mode=0664,dir_mode=0775,iocharset=utf8" ;; readonly) - MOUNT_OPTIONS="ro,file_mode=0444,dir_mode=0555,iocharset=utf8" - ;; - performance) - MOUNT_OPTIONS="rw,file_mode=0664,dir_mode=0775,iocharset=utf8,cache=strict,rsize=1048576,wsize=1048576" + MOUNT_OPTIONS="ro,noperm,file_mode=0444,dir_mode=0555,iocharset=utf8" ;; custom) MOUNT_OPTIONS=$(whiptail --inputbox "$(translate "Enter custom mount options:")" 10 70 "rw,file_mode=0664,dir_mode=0775" --title "$(translate "Custom Options")" 3>&1 1>&2 2>&3) [[ $? -ne 0 ]] && return 1 - [[ -z "$MOUNT_OPTIONS" ]] && MOUNT_OPTIONS="rw,file_mode=0664,dir_mode=0775" + [[ -z "$MOUNT_OPTIONS" ]] && MOUNT_OPTIONS="rw,noperm,file_mode=0664,dir_mode=0775" ;; *) - MOUNT_OPTIONS="rw,file_mode=0664,dir_mode=0775,iocharset=utf8" + MOUNT_OPTIONS="rw,noperm,file_mode=0664,dir_mode=0775,iocharset=utf8" ;; esac @@ -586,8 +559,8 @@ configure_host_mount_options() { fi + # Only ask about Proxmox storage if using username/password authentication if [[ "$USE_GUEST" != "true" ]]; then - if whiptail --yesno "$(translate "Do you want to add this as Proxmox storage?")\n\n$(translate "This will make the Samba share available as storage in Proxmox web interface.")" 10 70 --title "$(translate "Proxmox Storage")"; then PROXMOX_STORAGE=true @@ -611,6 +584,9 @@ configure_host_mount_options() { return 1 fi fi + else + # For guest access, don't offer Proxmox storage integration + PROXMOX_STORAGE=false fi return 0 @@ -667,41 +643,14 @@ add_proxmox_cifs_storage() { CONTENT_LIST="backup,iso,vztmpl" - if [[ "$USE_GUEST" == "true" ]]; then - msg_warn "$(translate "Attempting to add guest access storage to Proxmox...")" - - - PVESM_OUTPUT="" - PVESM_RESULT=1 - - msg_info "$(translate "Trying method 1: guest option...")" - PVESM_OUTPUT=$(pvesm add cifs "$storage_id" \ - --server "$server" \ - --share "$share" \ - --content "$CONTENT_LIST" \ - --options "guest" 2>&1) - PVESM_RESULT=$? - cleanup - - if [[ $PVESM_RESULT -ne 0 ]]; then - msg_info "$(translate "Trying method 2: without guest option...")" - PVESM_OUTPUT=$(pvesm add cifs "$storage_id" \ - --server "$server" \ - --share "$share" \ - --content "$CONTENT_LIST" 2>&1) - PVESM_RESULT=$? - cleanup - fi - - else - PVESM_OUTPUT=$(pvesm add cifs "$storage_id" \ - --server "$server" \ - --share "$share" \ - --username "$USERNAME" \ - --password "$PASSWORD" \ - --content "$CONTENT_LIST" 2>&1) - PVESM_RESULT=$? - fi + msg_info "$(translate "Adding authenticated storage to Proxmox...")" + PVESM_OUTPUT=$(pvesm add cifs "$storage_id" \ + --server "$server" \ + --share "$share" \ + --username "$USERNAME" \ + --password "$PASSWORD" \ + --content "$CONTENT_LIST" 2>&1) + PVESM_RESULT=$? if [[ $PVESM_RESULT -eq 0 ]]; then msg_ok "$(translate "CIFS storage added successfully to Proxmox!")" @@ -711,15 +660,16 @@ add_proxmox_cifs_storage() { 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_LIST${CL}" - echo -e "${TAB}${BGN}$(translate "Authentication:")${CL} ${BL}$([ "$USE_GUEST" == "true" ] && echo "Guest" || echo "User: $USERNAME")${CL}" + echo -e "${TAB}${BGN}$(translate "Authentication:")${CL} ${BL}User: $USERNAME${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 "${TAB}Error details: $PVESM_OUTPUT" + echo -e "${TAB}$(translate "Error details:"): $PVESM_OUTPUT" msg_warn "$(translate "The Samba share is still mounted, but not added as Proxmox storage.")" + 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}• $(translate "Command line:"): pvesm add cifs $storage_id --server $server --share $share --username $USERNAME --password [PASSWORD] --content backup,iso,vztmpl" @@ -757,14 +707,7 @@ mount_host_samba_share() { msg_title "$(translate "Mount Samba Share on Host")" - if ! test -d "$MOUNT_POINT"; then - if mkdir -p "$MOUNT_POINT"; then - msg_ok "$(translate "Mount point created on host.")" - else - msg_error "$(translate "Failed to create mount point on host.")" - return 1 - fi - fi + prepare_host_directory "$MOUNT_POINT" || return 1 if mount | grep -q "$MOUNT_POINT"; then @@ -782,6 +725,22 @@ mount_host_samba_share() { else CRED_OPTION="guest" fi + + + # --- Ensure correct group mapping --- + if [[ "$SHARE_COMMON_LOADED" == "true" ]]; then + GROUP=$(pmx_share_map_get "$MOUNT_POINT") + if [[ -z "$GROUP" ]]; then + GROUP=$(pmx_choose_or_create_group "sharedfiles") || return 1 + pmx_share_map_set "$MOUNT_POINT" "$GROUP" + fi + + HOST_GID=$(pmx_ensure_host_group "$GROUP" 101000) || return 1 + # Forzar que los ficheros/directorios se monten con este GID + MOUNT_OPTIONS="$MOUNT_OPTIONS,gid=$HOST_GID,uid=0" + msg_ok "$(translate "Directory prepared with shared group:") $GROUP (GID: $HOST_GID)" + fi + FULL_OPTIONS="$MOUNT_OPTIONS,$CRED_OPTION" @@ -1229,12 +1188,57 @@ test_host_samba_connectivity() { apt-get install -y cifs-utils smbclient &>/dev/null echo "$(translate "CIFS client tools installed.")" fi + + echo "" + echo "$(translate "ProxMenux Extensions:")" + if [[ "$SHARE_COMMON_LOADED" == "true" ]]; then + echo "$(translate "Shared Functions: LOADED")" + if [[ -f "$PROXMENUX_SHARE_MAP_DB" ]]; then + MAPPED_DIRS=$(wc -l < "$PROXMENUX_SHARE_MAP_DB" 2>/dev/null || echo "0") + echo "$(translate "Mapped directories:"): $MAPPED_DIRS" + fi + else + echo "$(translate "Shared Functions: NOT LOADED (using fallback methods)")" + fi echo "" msg_success "$(translate "Press Enter to return to menu...")" read -r } +prepare_host_directory() { + local mount_point="$1" + + if [[ "$SHARE_COMMON_LOADED" == "true" ]]; then + # Use common functions for advanced directory preparation + local group_name + group_name=$(pmx_choose_or_create_group "sharedfiles") + if [[ -n "$group_name" ]]; then + local host_gid + host_gid=$(pmx_ensure_host_group "$group_name") + if [[ -n "$host_gid" ]]; then + pmx_prepare_host_shared_dir "$mount_point" "$group_name" + pmx_share_map_set "$mount_point" "$group_name" + msg_ok "$(translate "Directory prepared with shared group:") $group_name (GID: $host_gid)" + return 0 + fi + fi + msg_warn "$(translate "Failed to use shared functions, using basic directory creation.")" + fi + + # Fallback: basic directory creation + if ! test -d "$mount_point"; then + if mkdir -p "$mount_point"; then + msg_ok "$(translate "Mount point created on host.")" + return 0 + else + msg_error "$(translate "Failed to create mount point on host.")" + return 1 + fi + fi + return 0 +} + # === Main Menu === while true; do CHOICE=$(dialog --backtitle "ProxMenux" --title "$(translate "Samba Host Manager - Proxmox Host")" \