homelab infrastructure services
at main 288 lines 9.9 kB view raw
1#!/bin/bash 2# tin machine rm - Remove machine environment 3 4set -euo pipefail 5 6# Get tinsnip root and source libraries 7SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 8TINSNIP_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")" 9source "$TINSNIP_ROOT/lib/core.sh" 10source "$TINSNIP_ROOT/lib/uid.sh" 11source "$TINSNIP_ROOT/lib/registry.sh" 12source "$TINSNIP_ROOT/lib/nas.sh" 13 14# Remove machine environment 15remove_machine() { 16 local service_env="$1" 17 local delete_data="${2:-false}" 18 local no_confirm="${3:-false}" 19 20 # Parse service-environment 21 local parsed_output 22 if ! parsed_output=$(parse_machine_name "$service_env" 2>/dev/null); then 23 error_with_prefix "Machine Remove" "Invalid machine environment format: '$service_env'" 24 echo "Expected: <service>-<environment> (e.g., pds-dev, bsky-pds-dev)" >&2 25 exit 1 26 fi 27 28 local service=$(echo "$parsed_output" | sed -n '1p') 29 local environment=$(echo "$parsed_output" | sed -n '2p') 30 local service_user="$service_env" 31 32 log_with_prefix "Machine Remove" "Removing machine: $service_env" 33 echo 34 35 # Check if user exists 36 if ! id "$service_user" &>/dev/null 2>&1; then 37 warn_with_prefix "Machine Remove" "User '$service_user' does not exist" 38 echo "Machine may have already been removed or never created." >&2 39 exit 0 40 fi 41 42 local service_uid=$(id -u "$service_user") 43 local mount_point="/mnt/$service_env" 44 45 echo "Machine Details:" 46 echo " User: $service_user" 47 echo " UID: $service_uid" 48 echo " Mount: $mount_point" 49 echo 50 51 # Check for deployed services 52 local services=() 53 if [[ -d "$mount_point/service" ]]; then 54 while IFS= read -r -d '' service_dir; do 55 services+=("$(basename "$service_dir")") 56 done < <(find "$mount_point/service" -mindepth 1 -maxdepth 1 -type d -print0 2>/dev/null) 57 fi 58 59 if [[ ${#services[@]} -gt 0 ]]; then 60 echo "WARNING: Found ${#services[@]} deployed service(s):" 61 for svc in "${services[@]}"; do 62 echo " - $svc" 63 done 64 echo 65 66 if [[ "$no_confirm" == "true" ]]; then 67 # Auto-confirm when called from sheet removal 68 log_with_prefix "Machine Remove" "Removing all services..." 69 else 70 read -p "Remove all services first? [Y/n]: " remove_services 71 case "${remove_services:-y}" in 72 [Yy]*|"") 73 ;; 74 *) 75 error_with_prefix "Machine Remove" "Cannot remove machine with deployed services" 76 echo "Remove services first with: tin service rm $service_env <service>" >&2 77 exit 1 78 ;; 79 esac 80 fi 81 82 for svc in "${services[@]}"; do 83 log_with_prefix "Machine Remove" "Removing service: $svc" 84 "$TINSNIP_ROOT/cmd/service/rm.sh" "$service_env" "$svc" <<< "y" 85 done 86 echo 87 fi 88 89 # Show data policy 90 if [[ "$delete_data" == "true" ]]; then 91 echo "WARNING: NAS data will be DELETED" 92 else 93 echo "SUCCESS: NAS data will be PRESERVED" 94 fi 95 echo 96 97 if [[ "$no_confirm" == "true" ]]; then 98 # Auto-confirm when called from sheet removal 99 log_with_prefix "Machine Remove" "Proceeding with removal..." 100 else 101 read -p "Remove this machine? [y/N]: " confirm 102 case "${confirm}" in 103 [Yy]) 104 log_with_prefix "Machine Remove" "Proceeding with removal..." 105 ;; 106 *) 107 log_with_prefix "Machine Remove" "Removal cancelled" 108 exit 0 109 ;; 110 esac 111 fi 112 113 # Delete NAS data if requested 114 if [[ "$delete_data" == "true" ]]; then 115 log_with_prefix "Machine Remove" "Deleting NAS data..." 116 117 # Find NAS server from fstab 118 local nas_path=$(grep "$mount_point" /etc/fstab 2>/dev/null | awk '{print $1}' | head -1) 119 if [[ -n "$nas_path" ]]; then 120 echo " NAS path: $nas_path" 121 local nas_server=$(echo "$nas_path" | cut -d: -f1) 122 local nas_dir=$(echo "$nas_path" | cut -d: -f2) 123 124 echo " Deleting data on NAS: $nas_server" 125 echo " This will require sudo password on the NAS..." 126 echo "" 127 128 # Use interactive SSH with -t flag to enable password prompt 129 # This also removes the NFS export and reloads 130 if ssh -t "$nas_server" "echo 'Removing NAS data and export...' && \ 131 sudo rm -rf '$nas_dir' && \ 132 echo 'Data deleted: $nas_dir' && \ 133 sudo sed -i '\|$nas_dir|d' /etc/exports && \ 134 echo 'Export removed from /etc/exports' && \ 135 sudo exportfs -ra && \ 136 echo 'NFS exports reloaded'"; then 137 echo "" 138 log_with_prefix "Machine Remove" "✅ NAS data and export deleted successfully" 139 else 140 echo "" 141 warn_with_prefix "Machine Remove" "Failed to delete NAS data" 142 echo " Manually delete with:" >&2 143 echo " ssh $nas_server" >&2 144 echo " sudo rm -rf '$nas_dir'" >&2 145 echo " sudo sed -i '\|$nas_dir|d' /etc/exports" >&2 146 echo " sudo exportfs -ra" >&2 147 fi 148 else 149 warn_with_prefix "Machine Remove" "Could not find NAS path in /etc/fstab" 150 echo " NFS mount information not available for cleanup" >&2 151 fi 152 else 153 log_with_prefix "Machine Remove" "Preserving NAS data (use --delete-data to remove)" 154 fi 155 156 # Unmount NFS 157 log_with_prefix "Machine Remove" "Unmounting NFS..." 158 if mountpoint -q "$mount_point" 2>/dev/null; then 159 sudo umount "$mount_point" 2>/dev/null || sudo umount -l "$mount_point" 160 fi 161 162 # Remove from fstab 163 log_with_prefix "Machine Remove" "Removing from /etc/fstab..." 164 sudo sed -i "\|$mount_point|d" /etc/fstab 165 166 # Remove user 167 log_with_prefix "Machine Remove" "Removing user $service_user..." 168 169 # Kill any processes owned by the user first 170 if id "$service_user" &>/dev/null; then 171 sudo pkill -9 -u "$service_user" 2>/dev/null || true 172 sleep 1 # Give processes time to terminate 173 fi 174 175 # Remove user and home directory 176 if sudo userdel -r "$service_user" 2>/dev/null; then 177 log_with_prefix "Machine Remove" "User removed successfully" 178 else 179 warn_with_prefix "Machine Remove" "Failed to remove user (may need manual cleanup)" 180 fi 181 182 # Remove mount point directory 183 if [[ -d "$mount_point" ]]; then 184 sudo rmdir "$mount_point" 2>/dev/null || sudo rm -rf "$mount_point" 185 fi 186 187 # Remove service from registry 188 log_with_prefix "Machine Remove" "Removing from machine registry..." 189 190 # Detect sheet from UID 191 local sheet=$(get_sheet_from_uid "$service_uid") 192 log_with_prefix "Machine Remove" "Detected sheet: $sheet (from UID $service_uid)" 193 194 if unregister_service "$service" "$sheet" 2>/dev/null; then 195 log_with_prefix "Machine Remove" "Service unregistered from $sheet registry" 196 else 197 warn_with_prefix "Machine Remove" "Service was not in registry for sheet $sheet" 198 fi 199 200 echo 201 log_with_prefix "Machine Remove" "Machine '$service_env' removed successfully" 202 if [[ "$delete_data" != "true" ]]; then 203 echo 204 log_with_prefix "Machine Remove" "NAS data preserved. To restore:" 205 log_with_prefix "Machine Remove" " tin machine create $service $environment <nas-server>" 206 log_with_prefix "Machine Remove" " tin service deploy $service_env <service-name>" 207 fi 208} 209 210show_help() { 211 cat << EOF 212tin machine rm - Remove machine environment 213 214USAGE: 215 tin machine rm <service-env> [--delete-data] [--no-confirm] 216 217DESCRIPTION: 218 Remove a machine environment including user and NFS mount. 219 By default, NAS data is PRESERVED for recovery. 220 Automatically removes all deployed services first. 221 222ARGUMENTS: 223 <service-env> Machine to remove (e.g., pds-dev) 224 225OPTIONS: 226 --delete-data Also delete data on NAS (DANGEROUS!) 227 --no-confirm Skip confirmation prompts (for automation) 228 229EXAMPLES: 230 tin machine rm pds-dev # Remove machine, keep NAS data 231 tin machine rm pds-dev --delete-data # Remove machine AND delete NAS data 232 tin machine rm pds-dev --no-confirm # Remove without prompts 233 234NOTES: 235 - Automatically removes deployed services (with confirmation unless --no-confirm) 236 - Default behavior preserves NAS data (CD-friendly) 237 - Machine can be recreated and data remounted for recovery 238 - Use --delete-data only when permanently decommissioning 239 - NAS deletion requires sudo password (interactive prompt) 240 - Also removes NFS export from /etc/exports and reloads 241 - --no-confirm keeps stdin as terminal for interactive NAS password 242 243WARNING: 244 --delete-data will PERMANENTLY DELETE all data on the NAS! 245 You will be prompted for the NAS sudo password during deletion. 246 247EOF 248} 249 250# Handle help flags 251case "${1:-}" in 252 --help|-h|help) 253 show_help 254 exit 0 255 ;; 256esac 257 258# Main execution 259if [[ $# -eq 0 ]]; then 260 error_with_prefix "Machine Remove" "Service environment required" 261 echo "Usage: tin machine rm <service-env> [--delete-data] [--no-confirm]" >&2 262 exit 1 263fi 264 265service_env="$1" 266delete_data="false" 267no_confirm="false" 268 269# Parse flags 270shift 271while [[ $# -gt 0 ]]; do 272 case "$1" in 273 --delete-data) 274 delete_data="true" 275 ;; 276 --no-confirm) 277 no_confirm="true" 278 ;; 279 *) 280 error_with_prefix "Machine Remove" "Unknown flag: $1" 281 echo "Usage: tin machine rm <service-env> [--delete-data] [--no-confirm]" >&2 282 exit 1 283 ;; 284 esac 285 shift 286done 287 288remove_machine "$service_env" "$delete_data" "$no_confirm"