Public/Invoke-FSMShareMigrationPrep.ps1
|
function Invoke-FSMShareMigrationPrep { <# .SYNOPSIS Runs the full export -> optional remap -> create -> grant -> compare workflow, with a clean summary at the end. .DESCRIPTION One-button orchestration of the whole share-prep process. It exports shares and permissions from the source, optionally remaps paths, creates the shares on the target, applies permissions, and verifies the result, then prints a tallied summary (Created / Skipped / Failed / etc.). SAFETY: preview by default; add -Execute to make changes. With -LogPath, all result objects are written to dated CSVs and a transcript is captured. .PARAMETER SourceServer The original file server. .PARAMETER TargetServer The new file server. .PARAMETER WorkingPath Folder for the generated CSVs (and logs, if -LogPath is not given separately). .PARAMETER OldRoot Optional. If both OldRoot and NewRoot are supplied, paths are remapped. .PARAMETER NewRoot Optional replacement root for OldRoot. .PARAMETER DefaultFullAccess Initial Full Access principal(s) at share creation. Default 'Everyone'. .PARAMETER Credential Optional credentials used for every remote connection. .PARAMETER LogPath Optional folder to write result CSVs and a transcript to. .PARAMETER RemoveEveryone Strip the default Everyone permission after applying real permissions. .PARAMETER Execute Actually create shares and apply permissions. Without it, everything is a preview. .EXAMPLE Invoke-FSMShareMigrationPrep -SourceServer oldfs01 -TargetServer newfs01 -WorkingPath C:\Temp\FSMig .EXAMPLE Invoke-FSMShareMigrationPrep -SourceServer oldfs01 -TargetServer newfs01 -WorkingPath C:\Temp\FSMig ` -OldRoot 'D:\Shares' -NewRoot 'E:\Data' -RemoveEveryone -LogPath C:\Temp\FSMig\Logs -Execute #> [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$SourceServer, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$TargetServer, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$WorkingPath, [string]$OldRoot, [string]$NewRoot, [string[]]$DefaultFullAccess = @('Everyone'), [pscredential]$Credential, [string]$LogPath, [switch]$RemoveEveryone, [switch]$Execute ) if (($OldRoot -and -not $NewRoot) -or ($NewRoot -and -not $OldRoot)) { throw "OldRoot and NewRoot must be supplied together (or neither)." } if (-not (Test-Path -Path $WorkingPath)) { New-Item -Path $WorkingPath -ItemType Directory -Force | Out-Null } $transcriptStarted = $false if ($LogPath) { if (-not (Test-Path -Path $LogPath)) { New-Item -Path $LogPath -ItemType Directory -Force | Out-Null } $stamp = Get-Date -Format 'yyyyMMdd-HHmmss' try { Start-Transcript -Path (Join-Path $LogPath "FSMigration-$stamp.log") -ErrorAction Stop | Out-Null $transcriptStarted = $true } catch { Write-FSMStatus -Message "Could not start transcript: $($_.Exception.Message)" -Level Warning } } try { $mode = if ($Execute) { 'EXECUTE (changes will be made)' } else { 'PREVIEW (no changes)' } Write-FSMStatus -Message "File share migration prep | $SourceServer -> $TargetServer | Mode: $mode" -Level Information $shareCsv = Join-Path $WorkingPath "$SourceServer-shares.csv" $permissionCsv = Join-Path $WorkingPath "$SourceServer-share-permissions.csv" $targetShareCsv = $shareCsv Export-FSMShareInventory -SourceServer $SourceServer -OutputPath $shareCsv -Credential $Credential | Out-Null Export-FSMSharePermissions -SourceServer $SourceServer -OutputPath $permissionCsv -Credential $Credential | Out-Null if ($OldRoot -and $NewRoot) { $targetShareCsv = Join-Path $WorkingPath "$SourceServer-shares-remapped-for-$TargetServer.csv" Convert-FSMSharePath -InputPath $shareCsv -OutputPath $targetShareCsv -OldRoot $OldRoot -NewRoot $NewRoot | Out-Null } Write-FSMStatus -Message 'Creating target shares...' -Level Information $createResults = @(New-FSMTargetShares -TargetServer $TargetServer -ShareCsvPath $targetShareCsv ` -DefaultFullAccess $DefaultFullAccess -Credential $Credential -Execute:$Execute) Write-FSMStatus -Message 'Applying share permissions...' -Level Information $grantResults = @(Grant-FSMTargetSharePermissions -TargetServer $TargetServer -PermissionCsvPath $permissionCsv ` -RemoveEveryone:$RemoveEveryone -Credential $Credential -Execute:$Execute) Write-FSMStatus -Message 'Comparing source and target shares...' -Level Information $compareResults = @(Compare-FSMShareInventory -SourceServer $SourceServer -TargetServer $TargetServer -Credential $Credential) if ($LogPath) { $stamp = Get-Date -Format 'yyyyMMdd-HHmmss' $createResults | Export-Csv (Join-Path $LogPath "create-results-$stamp.csv") -NoTypeInformation -Encoding UTF8 $grantResults | Export-Csv (Join-Path $LogPath "grant-results-$stamp.csv") -NoTypeInformation -Encoding UTF8 $compareResults | Export-Csv (Join-Path $LogPath "compare-results-$stamp.csv") -NoTypeInformation -Encoding UTF8 } $createSummary = Show-FSMResultSummary -Result $createResults -Title 'Share creation' $grantSummary = Show-FSMResultSummary -Result $grantResults -Title 'Permission application' $missing = @($compareResults | Where-Object Status -eq 'MissingOnTarget') if ($missing.Count) { Write-FSMStatus -Message "$($missing.Count) share(s) still MISSING on target: $($missing.ShareName -join ', ')" -Level Warning } else { Write-FSMStatus -Message 'All source shares present on target.' -Level Success } # Return everything as one structured object for capture/automation. [pscustomobject]@{ Mode = if ($Execute) { 'Execute' } else { 'Preview' } CreateResults = $createResults GrantResults = $grantResults CompareResults = $compareResults CreateSummary = $createSummary GrantSummary = $grantSummary MissingOnTarget = $missing.ShareName } } finally { if ($transcriptStarted) { Stop-Transcript | Out-Null } } } |