We got some new disk shelves in to replace some old ones on our NetApp filer. The old disks had a lot of SnapMirror destination volumes.All these needed migrating to the new disks. Initially we were planning on creating a new set of SnapMirrors from the source volumes to the destinations, and once these were complete, remove the original mirrors. This seemed like a long winded wasteful process – we did not particularly want 30Tb of data re-transmitted over the network, especially as an fully internal transfer would run at a significantly higher speed.
Also, we wanted to automate this process as much as possible, as this provided the smallest scope for error.
Hence the following script was born.
It runs through quite a simple process:
- Load the DataONTAP PowerShell module if it is not available
- Connect to the specified filer
- Check that the source volume and the destination aggregate exist
- Get details of the NFS exports on the volume and remove all NFS exports
- Break the current SnapMirror relationship
- Perform a Volume Move of the now writeable SnapMirror destination
- Re-create the NFS exports
- Re-sync the SnapMirror
The NFS exports have to be removed, as volume moves are not supported on volumes that have any exports configured. As long as the script runs to the end, the exports will be recreated once everything has completed.
# ---------------------------------------------------------------------------------------------------------- # PURPOSE: Moves a SnapMirror Destination to a new aggregate, without re-initializing the SnapMirror from scratch. # # VERSION DATE USER DETAILS # 1 27/10/2014 Craig Tolley First version # 1.1 14/11/2014 Craig Tolley Added new parameter to pass in credentials, so that scripting multiple moves is easier and without prompts # # ---------------------------------------------------------------------------------------------------------- <# .Synopsis Moves the specified volume to a new aggregate. .EXAMPLE Move-SnapmirrorDestination -VolumeToMove Volume1 -DestinationAggr Aggr2 -FilerName Filer1 #> function Move-SnapmirrorDestination { [CmdletBinding()] Param ( # The volume that we want to move [Parameter(Mandatory=$true, ValueFromPipeline=$false, Position=0)] [String]$VolumeToMove, # The destination aggregate for the new volume [Parameter(Mandatory=$true, ValueFromPipeline=$false, Position=1)] [String]$DestinationAggr, # The filer name to connect to [Parameter(Mandatory=$true, ValueFromPipeline=$false, Position=2)] [String]$FilerName, [Parameter(Position=3)] [System.Management.Automation.PSCredential]$FilerCredentials ) #Check that that DataOnTap Module is available, check it is loaded. Write-Host "Checking for DataONTAP Module..." if ((Get-Module -ListAvailable | Where {$_.Name -eq "DataONTAP"}).Count -ne 1) { Write-Error "DataONTAP not installed on targeted machine" Exit 1 } if ((Get-Module | Where {$_.Name -eq "DataONTAP"}).Count -ne 1) { Write-Host "Importing DataONTAP Module..." Import-Module -Name "DataONTAP" | Out-Null } #If we have not been passed credentials, then prompt for them. If ($FilerCredentials -eq $null) {$FilerCredentials = Get-Credential -Message "Please supply credentials for $FilerName"} #Connect to the Filer. Write-Host "Connecting to $FilerName" -BackgroundColor Yellow -ForegroundColor Black $Error.Clear() Connect-NaController -Name $FilerName -Credential $FilerCredentials If ($Error.Count -gt 0) { Write-Host "There was an error connecting to the filer. Please check your credentials and try again." Break } Write-Host "" #Get the Source Volume Write-Host "Getting details of Volume: $VolumeToMove" -BackgroundColor Yellow -ForegroundColor Black $SrcVolume = Get-NaVol $VolumeToMove If ($Error.Count -gt 0) { Write-Host "There was an error getting the details of the Volume. Please check that the volume name is correct and the volume is online." Break } $SrcVolume | ft #Get the Destination Aggregate Write-Host "Getting details of the destination aggregate: $DestinationAggr" -BackgroundColor Yellow -ForegroundColor Black $DestAggr = Get-NaAggr $DestinationAggr If ($Error.Count -gt 0) { Write-Host "There was an error getting the details of the Volume. Please check that the volume name is correct and the volume is online." Break } $DestAggr | ft #Get the NFS Exports for the Volume and Remove them Write-Host "Getting details of the NFS Exports" -BackgroundColor Yellow -ForegroundColor Black $NFSExports = Get-NaNfsExport | Where {$_.Pathname -like "*$($SrcVolume.Name)"} If (($NFSExports).Count -gt 0) { ForEach ($Exp in $NFSExports) {Remove-NaNfsExport $Exp} } Else {Write-Host "No NFS Exports are configured for this volume"} Write-Host "" #Break all of the snapmirrors which are configured Write-Host "Breaking existing Snapmirrors" -BackgroundColor Yellow -ForegroundColor Black $SrcSnapMirrors = Get-NaSnapmirror $SrcVolume $SrcSnapMirrors | ft If (($SrcSnapMirrors).Count -gt 0) { ForEach ($Snapmirror in $SrcSnapMirrors) {Get-NASnapMirror $Snapmirror.Destination | Invoke-NaSnapmirrorBreak -Confirm:$false | Out-Null} } Else {Write-Host "No Snapmirrors are configured for this volume"} Write-Host "" #Start the actual volume move. Write-Host "Starting the Vol Move (Update every 15 seconds)" -BackgroundColor Yellow -ForegroundColor Black Start-NaVolMove -Volume $SrcVolume -DestAggr $DestAggr #Keep Running Until the Vol Move completes Get-NaVolMove | Where {$_.SourceVolumeName -eq $SrcVolume.Name} | ft Do { Get-NaVolMove | Where {$_.SourceVolumeName -eq $SrcVolume.Name} | ft -HideTableHeaders Start-Sleep 15 } Until ((Get-NaVolMove | Where {$_.SourceVolumeName -eq $SrcVolume.Name}).Count -eq 0) #Recreate the NFS Exports Write-Host "Recreating the NFS Exports" -BackgroundColor Yellow -ForegroundColor Black ForEach ($Exp in $NFSExports) {Add-NaNfsExport $Exp} Write-Host "" #Resync all of the snapmirrors which are configured Write-Host "Re-synching all SnapMirrors" -BackgroundColor Yellow -ForegroundColor Black If (($SrcSnapMirrors).Count -gt 0) { ForEach ($Snapmirror in $SrcSnapMirrors) {Get-NASnapMirror $Snapmirror.Destination | Invoke-NaSnapmirrorResync -Confirm:$false | Out-Null} } #Complete Write-Host " -- Completed Volume Move -- " }
If you wanted to use this to move a bunch of destinations to a new volume, then a short snippet like this does the job for you:
$VolsToMove = "volA", "volB" $FilerLogin = Get-Credential ForEach($v in $VolsToMove) {Move-SnapmirrorDestination -VolumeToMove $v -DestinationAggr newAggr -FilerName Filer1 -FilerCredentials $FilerLogin}