#Requires -RunAsAdministrator <# .SYNOPSIS Phase 2.3: Sync data from Synology NAS to CS-SERVER. .DESCRIPTION Uses robocopy to pull all shared folder data from the Synology NAS (192.168.0.120) to D:\Shares on CS-SERVER. Creates missing folders and SMB shares. Run on CS-SERVER via ScreenConnect. .NOTES - Synology must be accessible at \\192.168.0.120 - Run BEFORE phase2-file-shares.ps1 (permissions are set after sync) - First run may take hours depending on data size - Subsequent runs are incremental (robocopy only copies changes) - /MIR is NOT used to avoid accidental deletion — uses /E instead #> $NAS = "192.168.0.120" $DestRoot = "D:\Shares" Write-Host "=== Phase 2.3: Synology Data Sync ===" -ForegroundColor Cyan Write-Host "" # --- Test NAS connectivity --- Write-Host "--- Testing NAS connectivity ---" -ForegroundColor Yellow $ping = Test-Connection -ComputerName $NAS -Count 2 -Quiet -ErrorAction SilentlyContinue if (-not $ping) { Write-Host "[FAIL] Cannot reach $NAS — aborting" -ForegroundColor Red exit 1 } Write-Host " [OK] $NAS is reachable" -ForegroundColor Green # Test SMB access try { $testPath = Test-Path "\\$NAS\Public" -ErrorAction Stop if ($testPath) { Write-Host " [OK] SMB access to \\$NAS works" -ForegroundColor Green } else { Write-Host " [WARN] \\$NAS\Public not accessible — may need credentials" -ForegroundColor Yellow Write-Host " Run: net use \\$NAS /user:admin " -ForegroundColor Yellow } } catch { Write-Host " [WARN] SMB access test failed: $_" -ForegroundColor Yellow Write-Host " You may need to map the NAS first:" -ForegroundColor Yellow Write-Host " net use \\$NAS /user:admin " -ForegroundColor Yellow } # --- Define sync jobs --- # Source (Synology share name) -> Destination folder on CS-SERVER $syncJobs = @( @{ Name = "Management"; Source = "\\$NAS\Management"; Dest = "$DestRoot\Management" } @{ Name = "SalesDept"; Source = "\\$NAS\SalesDept"; Dest = "$DestRoot\SalesDept" } @{ Name = "Server"; Source = "\\$NAS\Server"; Dest = "$DestRoot\Server" } @{ Name = "chat"; Source = "\\$NAS\chat"; Dest = "$DestRoot\chat" } @{ Name = "Public"; Source = "\\$NAS\Public"; Dest = "$DestRoot\Public" } @{ Name = "homes"; Source = "\\$NAS\homes"; Dest = "$DestRoot\homes" } ) # --- Create destination folders --- Write-Host "`n--- Creating destination folders ---" -ForegroundColor Yellow foreach ($job in $syncJobs) { if (-not (Test-Path $job.Dest)) { New-Item -Path $job.Dest -ItemType Directory -Force | Out-Null Write-Host " [OK] Created $($job.Dest)" -ForegroundColor Green } else { Write-Host " [SKIP] $($job.Dest) already exists" -ForegroundColor DarkGray } } # --- Sync each share --- Write-Host "`n--- Syncing data (this may take a while) ---" -ForegroundColor Yellow Write-Host "" $logDir = "$DestRoot\IT\Backups\SyncLogs" New-Item -Path $logDir -ItemType Directory -Force | Out-Null foreach ($job in $syncJobs) { Write-Host "=== Syncing: $($job.Name) ===" -ForegroundColor Cyan Write-Host " From: $($job.Source)" -ForegroundColor DarkGray Write-Host " To: $($job.Dest)" -ForegroundColor DarkGray # Check if source is accessible if (-not (Test-Path $job.Source)) { Write-Host " [SKIP] Source not accessible: $($job.Source)" -ForegroundColor Yellow continue } $logFile = "$logDir\sync-$($job.Name)-$(Get-Date -Format 'yyyy-MM-dd_HHmm').log" # Robocopy options: # /E = copy subdirectories including empty ones # /Z = restartable mode (resume on network interruption) # /COPY:DAT = copy Data, Attributes, Timestamps (no permissions — we set those separately) # /R:3 = retry 3 times on failure # /W:5 = wait 5 seconds between retries # /MT:8 = 8 threads for parallel copy # /XD = exclude directories (@ prefixed Synology system dirs) # /LOG = log to file # /NP = no progress percentage (cleaner log) # /TEE = output to console AND log file $roboArgs = @( $job.Source, $job.Dest, "/E", "/Z", "/COPY:DAT", "/R:3", "/W:5", "/MT:8", "/XD", "@eaDir", "@tmp", "#recycle", "#snapshot", "/XF", "Thumbs.db", ".DS_Store", "desktop.ini", "/LOG:$logFile", "/NP", "/TEE" ) $startTime = Get-Date & robocopy @roboArgs $exitCode = $LASTEXITCODE $elapsed = (Get-Date) - $startTime # Robocopy exit codes: 0=no change, 1=files copied, 2=extras, 4=mismatches, 8+=errors if ($exitCode -lt 8) { Write-Host " [OK] $($job.Name) synced in $([math]::Round($elapsed.TotalMinutes, 1)) minutes (exit code: $exitCode)" -ForegroundColor Green } else { Write-Host " [ERROR] $($job.Name) had errors (exit code: $exitCode) — check $logFile" -ForegroundColor Red } Write-Host "" } # --- Summary --- Write-Host "=== Sync Complete ===" -ForegroundColor Cyan Write-Host "" Write-Host "Folder sizes:" -ForegroundColor Yellow foreach ($job in $syncJobs) { if (Test-Path $job.Dest) { $size = (Get-ChildItem $job.Dest -Recurse -File -ErrorAction SilentlyContinue | Measure-Object Length -Sum).Sum $sizeGB = [math]::Round($size / 1GB, 2) $fileCount = (Get-ChildItem $job.Dest -Recurse -File -ErrorAction SilentlyContinue).Count Write-Host " $($job.Name): $sizeGB GB ($fileCount files)" -ForegroundColor Cyan } } Write-Host "" Write-Host "Sync logs saved to: $logDir" -ForegroundColor Green Write-Host "Next: Run phase2-file-shares.ps1 to set permissions and create SMB shares" -ForegroundColor Green