183 lines
5.2 KiB
Python
183 lines
5.2 KiB
Python
#!/usr/bin/env python3
|
|
import os
|
|
import subprocess
|
|
import shutil
|
|
import time
|
|
from pathlib import Path
|
|
from urllib.parse import quote
|
|
from dataclasses import dataclass
|
|
from typing import Optional
|
|
|
|
|
|
@dataclass
|
|
class SMBConfig:
|
|
"""Configuration for an SMB mount."""
|
|
server: str
|
|
share: str
|
|
username: str
|
|
password: str
|
|
mount_name: str # Name for the mount folder (e.g., "GDriveNetwork")
|
|
local_dest: Optional[str] = None # Optional local destination for syncing
|
|
|
|
@property
|
|
def mount_point(self) -> str:
|
|
"""Returns the full mount point path."""
|
|
return str(Path.home() / "NetworkMounts" / self.mount_name)
|
|
|
|
|
|
def is_mounted(mount_point: str) -> bool:
|
|
"""Check if a path is currently mounted."""
|
|
return os.path.ismount(mount_point)
|
|
|
|
|
|
def mount_share(config: SMBConfig) -> bool:
|
|
"""
|
|
Mount an SMB share using the provided configuration.
|
|
Returns True if successful, False otherwise.
|
|
"""
|
|
mount_point = config.mount_point
|
|
|
|
# Create mount point directory if it doesn't exist
|
|
Path(mount_point).mkdir(parents=True, exist_ok=True)
|
|
|
|
# Build the SMB URL
|
|
# Format: //username:password@server/share
|
|
if config.username and config.password:
|
|
escaped_pass = quote(config.password, safe='')
|
|
smb_url = f"//{config.username}:{escaped_pass}@{config.server}/{config.share}"
|
|
else:
|
|
smb_url = f"//{config.server}/{config.share}"
|
|
|
|
# Mount command for macOS
|
|
cmd = ["mount_smbfs", smb_url, mount_point]
|
|
|
|
try:
|
|
print(f"Mounting {config.share} from {config.server}...")
|
|
subprocess.run(cmd, check=True, capture_output=True, text=True)
|
|
print(f"Successfully mounted to {mount_point}")
|
|
return True
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"Failed to mount: {e.stderr}")
|
|
return False
|
|
|
|
|
|
def unmount_share(config: SMBConfig) -> bool:
|
|
"""Unmount an SMB share."""
|
|
mount_point = config.mount_point
|
|
|
|
if not is_mounted(mount_point):
|
|
print(f"{mount_point} is not mounted.")
|
|
return True
|
|
|
|
try:
|
|
subprocess.run(["umount", mount_point], check=True, capture_output=True, text=True)
|
|
print(f"Successfully unmounted {mount_point}")
|
|
return True
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"Failed to unmount: {e.stderr}")
|
|
return False
|
|
|
|
|
|
def ensure_mounted(config: SMBConfig) -> bool:
|
|
"""
|
|
Ensure a share is mounted. Mount it if not already mounted.
|
|
Returns True if mounted (or already was), False if mount failed.
|
|
"""
|
|
mount_point = config.mount_point
|
|
|
|
if is_mounted(mount_point):
|
|
print(f"{config.share} is already mounted at {mount_point}")
|
|
return True
|
|
|
|
print(f"{config.share} not mounted. Attempting to mount...")
|
|
return mount_share(config)
|
|
|
|
|
|
# -----------------------------
|
|
# PREDEFINED CONFIGURATIONS
|
|
# -----------------------------
|
|
# Add your different mount configurations here
|
|
|
|
CONFIGS = {
|
|
"gdrive": SMBConfig(
|
|
server="192.168.1.68",
|
|
share="GDrive",
|
|
username="macos",
|
|
password="dromischSYNC123987me",
|
|
mount_name="GDrive",
|
|
local_dest="/Users/dromisch/NetworkMounts/GDrive"
|
|
),
|
|
|
|
# Example: Add more configurations as needed
|
|
# "photos": SMBConfig(
|
|
# server="192.168.1.68",
|
|
# share="Photos",
|
|
# username="photouser",
|
|
# password="photopass",
|
|
# mount_name="PhotosNetwork",
|
|
# local_dest="/Volumes/ExtraDrive/Photos"
|
|
# ),
|
|
|
|
# "backup": SMBConfig(
|
|
# server="192.168.1.100",
|
|
# share="Backups",
|
|
# username="backupuser",
|
|
# password="backuppass",
|
|
# mount_name="BackupNetwork"
|
|
# ),
|
|
}
|
|
|
|
|
|
def list_configs():
|
|
"""Print available configurations."""
|
|
print("Available mount configurations:")
|
|
for name, config in CONFIGS.items():
|
|
status = "mounted" if is_mounted(config.mount_point) else "not mounted"
|
|
print(f" {name}: //{config.server}/{config.share} ({status})")
|
|
|
|
|
|
def main():
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(description="Mount SMB network shares")
|
|
parser.add_argument("config", nargs="?", help="Configuration name to mount")
|
|
parser.add_argument("-l", "--list", action="store_true", help="List available configurations")
|
|
parser.add_argument("-u", "--unmount", action="store_true", help="Unmount instead of mount")
|
|
parser.add_argument("-a", "--all", action="store_true", help="Mount/unmount all configurations")
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.list:
|
|
list_configs()
|
|
return
|
|
|
|
if args.all:
|
|
for name, config in CONFIGS.items():
|
|
print(f"\n--- {name} ---")
|
|
if args.unmount:
|
|
unmount_share(config)
|
|
else:
|
|
ensure_mounted(config)
|
|
return
|
|
|
|
if not args.config:
|
|
parser.print_help()
|
|
print("\n")
|
|
list_configs()
|
|
return
|
|
|
|
if args.config not in CONFIGS:
|
|
print(f"Unknown configuration: {args.config}")
|
|
list_configs()
|
|
return
|
|
|
|
config = CONFIGS[args.config]
|
|
|
|
if args.unmount:
|
|
unmount_share(config)
|
|
else:
|
|
ensure_mounted(config)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |