PowerShell: Move SnapMirror Destinations to a New Aggregate (7-Mode)

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}

1 person found this post useful.


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.