The MigrateDatasourceDataFromDPM script can have many formats one of which is to migrate a source disk to a target disk or array of disks. How much space do you need to migrate? You need at least as much as the source disk size of course but what if 1 or more volumes span to another disk? Take the sample below; you have Disk-1 and Disk-2 (both 750GB) with 4 volumes, note that volume V3 (green) spans Disk-1 and Disk-2.
If you want to migrate Disk-1 you have to migrate V1, V2 and all of V3 which totals to more than the size of Disk-1. Given possible spanning scenarios this is more challenging than you might expect. If all involved volumes are replica volumes it is fairly straight forward (“Get-DPMdisk” gives you all replicas) but if 1 or more are recovery point volumes it becomes a different ballgame. The script below figures that out and the synopsis explains how it does that.
#begin script #--------------param([string] $global:Debug) # SYNOPSIS # We first get lists we need to select from and reference against # Feed all DPM disks to GetMigSizeByDisk() # GetMigSizebyDisk() # walk all PGmembers on given disk # need to check if recovery point volumes are on same disk (PGmember[] are only replicas) # get recovery point volume from volume-list by VolumesetId (from member) and size not equal to replica # get recovery point extents from extents-list and see if any DiskId matches current disk identifier # when it does, we need to account for replica + shadowcopyarea sizes else just replica # next member until all members on disk done # return total size
function GetMigSizeByDisk{ param($disk, $extents, $dss, $Vols ) [int64]$size = 0 #For all data source members on current disk foreach ($m in ($disk.PgMember | Sort-Object -Property volumesetid -Unique)) { #we use ds to take sizes from rather than selects and sum proper extents $ds = $dss | ? {$m.DatasourceId -eq $_.id} $datasource = @($disk.pgmember | ? {$m.volumesetid -eq $_.volumesetid}) write-host if ($datasource.count -gt '1') {write-host " Datasources below are co-located" -f yellow} foreach ($datasource1 in $datasource) { $datasource2 = $dss | ? { $datasource1.datasourceid -eq $_.id} write-host " " $datasource2 } $expr = "VolumeSetId='{0}' and usage = 2" -f $m.VolumeSetID, $vols.usage $RecoVolume = @($Vols.Select("$expr")) $RecoExpr = "Guidname='{0}'" -f $RecoVolume[0].GuidName $RecoExtents = @($extents.Select("$RecoExpr")) # At least 1 recovery point volume extent lives on same disk as replica # We must now add shadowcopy size to total $size += $ds.ReplicaSize + $ds.ShadowCopyAreaSize #$includes all extents whereever they are $expr = "VolumeSetId='{0}' and usage = 1" -f $m.VolumeSetID, $vols.usage $Replica = $Vols.Select("$expr") $expr = "guidname= '{0}'" -f $replica[0].guidname $replica2 = $extents.select("$expr") foreach ($replica1 in $replica2) { if ($debug -eq 'DEBUG') { write-host " Replica volume Size - $('{0,8:N2}'-f($replica1.extentsize/$GB)) GB - Replica on Disk $('{0,3}'-f($replica1.ntdisknumber)) - Volume GUID " $replica1.Guidname -f green } else { write-host " Replica volume Size - $('{0,8:N2}'-f($replica1.extentsize/$GB)) GB - Replica on Disk $('{0,3}'-f($replica1.ntdisknumber))" -f green }
} $expr = "VolumeSetId='{0}' and usage = 2" -f $m.VolumeSetID, $vols.usage $Recovery = @($Vols.Select("$expr")) $expr = "guidname= '{0}'" -f $recovery[0].guidname $recovery2 = $extents.select("$expr") foreach ($recovery1 in $recovery2) { if ($debug -eq 'debug') { write-host " Recovery volume size - $('{0,8:N2}' -f($recovery1.Extentsize/$GB)) GB - Recovey on Disk $('{0,3}' -f($recovery1.ntdisknumber)) - Volume GUID " $recovery1.Guidname -f green } else { write-host " Recovery volume size - $('{0,8:N2}' -f($recovery1.Extentsize/$GB)) GB - Recovey on Disk $('{0,3}' -f($recovery1.ntdisknumber))" -f green } } } return $size }
$debug=$debug.ToUpper()$version = "v1.5" $global:MB = 1024 * 1024 $global:GB = $MB * 1024 $global:dpmservername = @(hostname) $ConfirmPreference = 'None'
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") >> $null #get sqlserver and instane from registry $reg = Get-ChildItem "HKLM:\Software\Microsoft\Microsoft Data Protection Manager" $sqlservername = $reg.GetValue(5).getvalue("sqlserver") $instance = $reg.GetValue(5).getvalue("instancename") $servername = "$sqlservername\$instance" $srvr = new-object ("Microsoft.SqlServer.Management.Smo.Server") $servername $db = $srvr.Databases["DPMDB"]
#get disks, volume, extents and datasource lists once $VolTable = $db.ExecutewithResults(" select * from tbl_SPM_Volume where VolumeSetID is not null ").Tables[0] # $extentlist = $db.ExecutewithResults(" select * from tbl_SPM_Extent").Tables[0] $extentlist = $db.ExecutewithResults(" select extent.diskid, extent.DiskOffset, extent.GuidName, extent.ExtentSize,disk.NTDiskNumber from tbl_SPM_Extent extent join tbl_SPM_Disk disk on extent.DiskID = disk.DiskID").Tables[0]
$disks = @(Get-DPMDisk "$dpmservername" ) | sort -Property NtDiskId $datasourcelist = Get-Datasource "$dpmservername"
#Now go to work Write-Host ("`nMigrateSpaceNeeded $version evaluating {0} DPM disks...`n" -f $disks.count) -f yellow foreach ($d in $disks) { write-host (" ==> Checking Datasources on Disk-{0}" -f $d.NtDiskID) -f cyan $MigSize = ( (GetMigSizeByDisk $d $extentlist $datasourcelist $Voltable)/ $GB).Tostring("N2") write-host; Write-Host (" ==> to migrate Disk-{0} you need $MigSize GB on the destination" -f $d.NtDiskID) -f cyan; write-host } Write-Host "`nDone!`n" -f white
#-------------- #end script