By Steven Jordan on April 15th, 2014.
There are times when DPM fails to remove expired recovery points. PruneVSS.ps1 can remove excessive disk (i.e., not tape) based recovery points.
#Author : Ruud Baars
#Date : 11/09/2008
#Edited : 11/15/2012 By: Wilson S.
#edited : 11:27:2012 By: Mike J.
#Edited : 3/25/2014 By: Steven J.
# $VerbosePreference = "Continue"
# NOTE: Update script to only remove recovery points on Disk. Recovery points removed will be from the oldest one up to the date
# entered by the user while the script is running
#deletes all recovery points before 'now' on selected data source.
$version="V4.7"
$ErrorActionPreference = "silentlycontinue"
add-pssnapin sqlservercmdletsnapin100
Add-PSSnapin -Name Microsoft.DataProtectionManager.PowerShell
#display RP's to delete and ask to continue.
#Check & wait data source to be idle else removal may fail (in Mojito filter on 'intent' to see the error)
#Fixed prune default and logfile name and some logging lines (concatenate question + answer)
#Check dependent recovery points do not pass BEFORE date and adjust selection to not select those ($reselect)
#--- Fixed reselect logic to keep adjusting reselect for as long as older than BEFORE date
#--- Fixed post removal rechecking logic to match what is done so far (was still geared to old logic)
#--- Modified to remove making RP and ask for pruning, fixed logic for removal rechecking logic
$MB=1024*1024
$logfile="DPMdeleteRP.LOG"
$wait=10
#seconds
$confirmpreference = "None"
function Show_help
{
cls
$l="=" * 79
write-host $l -foregroundcolor magenta
write-host -nonewline "`t<<<" -foregroundcolor white
write-host -nonewline " DANGEROUS :: MAY DELETE MANY RECOVERY POINTS " -foregroundcolor red
write-host ">>>" -foregroundcolor white
write-host $l -foregroundcolor magenta
write-host "Version: $version" -foregroundcolor cyan
write-host "A: User Selects data source to remove recovery points for" -foregroundcolor green
write-host "B: User enters date / time (using 24hr clock) to Delete recovery points" -foregroundcolor green
write-host "C: User Confirms deletion after list of recovery points to be deleted is displayed." -foregroundcolor green
write-host "Appending to log file $logfile`n" -foregroundcolor white
write-host "User Accepts all responsibilities by entering a data source or just pressing [Enter] " -foregroundcolor white -backgroundcolor blue
}
"**********************************" >> $logfile
"Version $version" >> $logfile
get-date >> $logfile
show_help
$DPMservername=&"hostname"
"Selected DPM server = $DPMservername" >> $logfile
write-host "`nConnnecting to DPM server retrieving data source list...`n" -foregroundcolor green
$pglist = @(Get-ProtectionGroup $DPMservername) # WILSON - Created PGlist as array in case we have a single protection group.
$ds=@()
$tapes=$null
$count = 0
$dscount = 0
foreach ($count in 0..($pglist.count - 1))
{
# write-host $pglist[$count].friendlyname
$ds += @(get-datasource $pglist[$count]) # WILSON - Created DS as array in case we have a single protection group.
# write-host $ds
# write-host $count -foreground yellow
}
if ( Get-Datasource $DPMservername -inactive) {$ds += Get-Datasource $DPMservername -inactive}
$i=0
write-host "Index Protection Group Computer Path"
write-host "---------------------------------------------------------------------------------"
foreach ($l in $ds)
{
"[{0,3}] {1,-20} {2,-20} {3}" -f $i, $l.ProtectionGroupName, $l.psinfo.netbiosname, $l.logicalpath
$i++
}
$DSname=read-host "`nEnter a data source index from list above - Note co-located datasources on same replica will be effected"
if (!$DSname)
{
write-host "No datasource selected `n" -foregroundcolor yellow
"Aborted on Datasource name" >> $logfile
exit 0
}
$DSselected=$ds[$DSname]
if (!$DSselected)
{
write-host "No datasource selected `n" -foregroundcolor yellow
"Aborted on Datasource name" >> $logfile
exit 0
}
$rp=get-recoverypoint $DS[$dsname]
$rp
# $DoTape=read-host "`nDo you want to remove when recovery points are on tape ? [y/N]"
# "Remove tape recovery point = $DoTape" >> $logfile
write-host "`nCollecting recoverypoint information for datasource $DSselected.name" -foregroundcolor green
if ($DSselected.ShadowCopyUsedspace -gt 0)
{
while ($DSSelected.TotalRecoveryPoints -eq 0)
{ # "still 0"
}
#this is on disk
$oldShadowUsage=[math]::round($DSselected.ShadowCopyUsedspace/$MB,1)
$line=("Total recoverypoint usage {0} MB on DISK in {1} recovery points" -f $oldShadowUsage ,$DSselected.TotalRecoveryPoints )
$line >> $logfile
write-host $line`n -foregroundcolor white
}
#this is on tape
#$trptot=0
#$tp= Get-RecoveryPoint($dsselected) | where {($_.Datalocation -eq "Media")}
#foreach ($trp in $tp) {$trptot += $trp.size }
#if ($trptot -gt 0 )
#{
# $line=("Total recoverypoint usage {0} MB on TAPE in {1} recovery points" -f ($trptot/$MB) ,$DSselected.TotalRecoveryPoints )
# $line >> $logfile
# write-host $line`n -foregroundcolor white
#}
[datetime]$afterdate="1/1/1980"
#$answer=read-host "`nDo you want to delete recovery points from the beginning [Y/n]"
#if ($answer -eq "n" )
#{
# [datetime]$afterdate=read-host "Delete recovery points AFTER date [MM/DD/YYYY hh:mm]"
#}
[datetime]$enddate=read-host "Delete ALL Disk based recovery points BEFORE and Including date/time entered [MM/DD/YYYY hh:mm]"
"Deleting recovery points until $enddate" >>$logfile
write-host "Deleting recovery points until and $enddate" -foregroundcolor yellow
$rp=get-recoverypoint $DSselected
if ($DoTape -ne "y" )
{
$RPselected=$rp | where {($_.representedpointintime -le $enddate) -and ($_.Isincremental -eq $FALSE)-and ($_.DataLocation -eq "Disk")}
}
else
{
$RPselected=$rp | where {($_.representedpointintime -le $enddate) -and ($_.Isincremental -eq $FALSE)}
}
if (!$RPselected)
{
write-host "No recovery points found!" -foregroundcolor yellow
"No recovery points found, aborting...!" >> $logfile
exit 0
}
$reselect = $enddate
$adjustflag = $false
foreach ($onerp in $RPselected)
{
$rtime=[string]$onerp.representedpointintime
$rsize=[math]::round(($onerp.size/$MB),1)
$line= "Found {0}, RP size= {1} MB (If 0 MB, co-located datasource cannot be computed), Incremental={2} "-f $rtime, $rsize,$onerp.Isincremental
$line >> $logfile
write-host "$line" -foregroundcolor yellow
#
#Get dependent rp's for data source
#
$allRPtbd=$DSselected.GetAllRecoveryPointsToBeDeleted($onerp)
foreach ($oneDrp in $allRPtbd)
{
if ($oneDrp.IsIncremental -eq $FALSE) {continue}
$rtime=[string]$oneDrp.representedpointintime
$rsize=[math]::round(($oneDrp.size/$MB),1)
$line= ("`t...is dependancy for {0} size {1} `tIncremental={2}" -f $rtime, $rsize, $oneDrp.Isincremental)
$line >> $logfile
if ($oneDrp.representedpointintime -ge $enddate)
{
#stick to latest full ($oneDrp = dependents, $onerp = full)
$adjustflag = $true
$reselect = $onerp.representedpointintime
"<< Dependents newer than BEFORE date >>>" >> $logfile
Write-Host -nonewline "`t <<< later than BEFORE date >>>" -foregroundcolor white -backgroundcolor red
write-host "$line" -foregroundcolor yellow
}
else
{
#Ok, include current latest incremental
$reselect = $oneDrp.representedpointintime
write-host "$line" -foregroundcolor yellow
}
}
}
if ($reselect -lt $oneDrp.representedpointintime)
{
#we adjusted further backward than latest incremental within selection
$reselect = $rtime
$line = "Adjusted BEFORE date to be $reselect to include dependents to $enddate"
$line >> $logfile
Write-Host $line -foregroundcolor white -backgroundcolor blue
}
$line="`n<<< SECOND TO LAST CHANCE TO ABORT - ONE MORE PROMPT TO CONFIRM. >>>"
write-host $line -foregroundcolor white -backgroundcolor blue
$line >> $logfile
$line="Above recovery points within adjusted range will be permanently deleted !!!"
write-host $line -foregroundcolor red
$line >> $logfile
$line="These RP's include dependent recovery points and may contain co-located datasource(s)"
write-host $line -foregroundcolor red
$line >> $logfile
$line="Data source activity = " + $DSselected.Activity
$line >> $logfile
write-host $line -foregroundcolor white
$DoDelete=""
while (($DoDelete -ne "N" ) -and ($DoDelete -ne "Y"))
{
$line="Continue with deletion (must answer) Y/N? "
write-host $line -foregroundcolor white
$DoDelete=read-host
$line = $line + $DoDelete
$line >> $logfile
}
if (!$DSselected.Activity -eq "Idle")
{
$line="Data source not idle, do you want to wait Y/N ? "
write-host $line -foregroundcolor yellow
$Y=read-host
$line = $line + $Y
$line >> $logfile
if ($Y -ieq "Y")
{
Write-Host "Waiting for data source to become idle..." -foregroundcolor green
while ($DSselected.Activity -ne "Idle")
{
("Waiting {0} seconds" -f $wait) >>$logfile
Write-Host -NoNewline "..." -ForegroundColor blue
start-sleep -s $wait
}
}
}
if ($DoDelete -eq "Y")
{
foreach ($onerp in $RPselected)
{
#reselect is adjusted to safe range relative to what was requested
#--- if adjustflag not set then all up to including else only older because we must keep the full
if ((($onerp.representedpointintime -le $reselect) -and ($adjustflag -eq $false)) -or ($onerp.representedpointintime -lt $reselect))
{
$rtime=[string]$onerp.representedpointintime
write-host `n$line -foregroundcolor red
$line >>$logfile
if (($onerp ) -and ($onerp.IsIncremental -eq $FALSE)) { remove-recoverypoint -RecoveryPoint $onerp -recurse -force -confirm:$False} # >> $logfile}
$line =("---`nDeleting recoverypoint -> " + $rtime)
$line >>$logfile
}
}
}
"All Done!" >> $logfile
write-host "`nAll Done!`n`n" -foregroundcolor white
$line="Do you want to View DPMdeleteRP.LOG file Y/N ? "
write-host $line -foregroundcolor white
$Y=read-host
$line = $line + $Y
$line >> $logfile
if ($Y -ieq "Y")
{
Notepad DPMdeleteRP.LOG}
By Steven Jordan on March 26th, 2013.
Takeaway: DPM 2010 can backup SQL 2012 with this simple permission change.
Problem: DPM 2010
cannot backup SQL 2012 databases.
- DPM 2010 Recovery Point Errors: Recovery point creation jobs for SQL Server
2012 database SERVER\NAME have been failing.
The number of failed recovery point creation jobs = x.
- DPM 2010 Replica is inconstant Alerts: The replica of SQL Server 2012 database
SERVER\NAME is inconsistent with the protected data source.
Solution: NT
AUTHORITY\System must be granted Sysadmin permissions on the SQL 2012 database instance.
Background: By default, SQL 2010 includes the Sysadmin permissions for the NT
Authority\System account. However, SQL
2012 does not include the Sysadmin
permissions for the NT Authority\System
account by default.
Fix DPM 2010 consistency errors for SQL 2012 databases by adding the Sysadmin server role to the SQL 2012 NT AUTHORITY\System:
1. Modify the NT Authority\System login:
2. Add Sysadmin
server role:
O #DPM #Consistency #SQL O
Reference: http://theessentialexchange.com/blogs/michael/default.aspx
By Steven Jordan on March 7th, 2013.
Takeaway: This walk through provides instructions on how to move the DPM SQL database to a new drive or directory location.
Problem: The system drive on the DPM server is consistently low on drive space. Low disk space creates havoc for Windows Updates and Volume Shadow Service (VSS) snapshots.
Background: The DPM system drive resides on a 64GB NTFS volume. The volume is nested on a Raid 1 partition which mirrors 2 x 64GB hard drives.
The system drive contains the DPM protection group mounting points; and uses iSCSI to connect to a SAN which stores the protection groups replica data.
The server was installed in 2010, and at the time 64GB seemed appropriate. Overtime, the limited space proved insufficient for our growing network.
Solution: Add storage and make configuration changes.
- Add new drives (2 x 146GB, RAID 1)
- Create new data volume.
- Move the DPM SQL database to the new volume.
- Complete additional DPM maintenance steps.
Steps:
- The Dell Open Manage Administrator makes adding additional drives a snap. Simply add the drives and configure the virtual disks for a new RAID 1 partition in the OMSA web GUI -no need to power off the server.
Use the Windows Disk Management to enable the disk and create a new NTFS volume.
- It's time to put that extra storage to good use. The DPM SQL database is close to 30GB in size, that's nearly half of the entire system drive! The DPM SQL database will be the first thing to go.
Let's stop the DPM services before we move the database: Server Manager → Configuration → Services → Stop the DPM services.
- Open the Microsoft SQL Server Management Studio to detach the DPM database. SQL Server Management Studio → Databases → right click the DPMDB database → left click on Detach.
Note that the DPMDB is no longer listed under the available databases.
- The DPM database is located in \\C:\Program Files\Microsoft DPM\DPM\DPMDB. Move the DPMDB directory to the new location.
- Attach the DPMDB database using Server Management Studio. SQL Server Management Studio → right click Databases →left click on attach → browse to the new DPMDB location.
Note the DPMDB is available in the Management Studio list of databases.
- Start the DPM service from the Server Manager (e.g., step 3).
- Use the DPM Management Shell to synchronize the database: DPMSync -sync.
- Start the DPM Administrator Console. N.B., all DPM replicas are in an inconsistent state.
Perform consistency check on every replica. The process can be manually performed or use PowerShell to a issue constancy check for all replicas.
- The primary DPM server will work great after the consistency check. The system drive now has nearly 30GB free.
- Run the DPMSync -sync on any other secondary DPM server and follow with consistency check to complete the process.
N.B., My first consistency checks failed with the following error: The VSS application writer or the VSS provider is in a bad state. The secondary DPM server's off-site protection group synchronized after I manually started the DPM Writer service on the primary DPM server.
- If the secondary DPM server protects the primary DPM server with a full metal backup the WindowsImageBackup location may be optionally changed to the new drive space.
The DPM server uses Windows Backup Server to backup its own System State. DPM runs the system state backup (SSB) on the system drive. Change the WindowsImageBackup location as follows:
- On the primary DPM server, navigate to c:\Program Files\Microsoft Data Protection Manager\DPM\Datasources.
- Edit PSDatasourceConfig.XML with notepad.
- Change the value from %systemdrive% to the new location.
- Save the file.
- On the secondary DPM server, run a consistency check on the system state backup protection group, which protects the primary DPM server.
- Wait for the check to fail. In the alerts, click Modify protection group, and complete the wizard steps.
- Perform consistency check on the same group.
That's It!
O #DPM #Consistency O
References:
http://technet.microsoft.com/en-us/library/ff634229.aspx
http://social.technet.microsoft.com/Forums/en-US/5e0deb70-ab35-4b1b-941f-70ab7ae0c792/permanently-changing-the-windowsimagebackup-location-in-dpm-2010?forum=dpmssandbmrbackup
|
Backup 2012 AD with 2010 DPM. |
Disclaimer: Microsoft does not support DPM 2010 backup for Windows 2012 servers. I have found however, the backup process still works. I have only run into 2 (resolvable) issues so far:
- Automatic installation of the DPM 2010 installation agent on Windows 2012 servers no longer works. The DPM agent must be installed manually. See my previous post on DPM for instructions.
- DPM 2010 backups of the system state for Windows 2012 server with Active Directory (AD) server installed failed.
Windows Server Backup must be installed on the Windows 2010 AD server in order to backup the system state. This is only true for 2012 servers with AD roles installed. After the Windows Server Backup feature was installed there were no longer problems with related DPM backups.
Problem: Data Protection Manager 2012 installation failed. The setup wizard stopped each attempt during the SQL installation. No specific error was provided. Some of the steps I went through:
- I confirmed all prerequisites had been installed.
- Googled for a solution
- Attempted to install DPM 2012 on both Windows 2012, and then on Windows 2008.
I was able to manually install SQL 2008R2 however another SQL license was then needed; which defeats the purpose of installing the free/included version of SQL2008 R2 standard when implemented though the DPM setup wizard.
Solution: The ISO image was bad. After much grief and wasted time I re-downloaded the DPM ISO image. I unpacked the contents on my workstation and copied the files to the server.
DPM 2012 & the included SQL server installed without any problems. Doh!
This is an update to a previous post on how to mark a tape as "free". Because of limitations with the DPM GUI a Power Shell script must be run to free the tapes associated with protection groups.
I ran into a problem specifying the location of the tape when using the previous script. The PS script below sidesteps the location problem.
N. B. Here is the correct format to run the script:
PS C:\scripts> .\free2.ps1 -dpmservername dpserver01 -LibraryName "Hewlett Packard DAT72 drive"
Here is the script:
param ([string] $DPMServerName, [string] $LibraryName)
if(("-?","-help") -contains $args[0])
{
Write-Host "Usage: ForceFree-Tape.ps1 [[-DPMServerName] ] [-LibraryName]
Write-Host "Example: Force-FreeTape.ps1 -Dpmservername SDPM01 -LibraryName My library
exit 0
}
if (!$DPMServerName)
{
$DPMServerName = Read-Host "DPM server name: "
if (!$DPMServerName)
{
Write-Error "Dpm server name not specified."
exit 1
}
}
if (!$LibraryName)
{
$LibraryName = Read-Host "Library name: "
if (!$LibraryName)
{
Write-Error "Library name not specified."
exit 1
}
}
if (!(Connect-DPMServer $DPMServerName))
{
Write-Error "Failed to connect To DPM server $DPMServerName"
exit 1
}
$library = Get-DPMLibrary $DPMServerName | where {$_.UserFriendlyName -eq $LibraryName}
write-host "Getting library..."
if (!$library)
{
Write-Error "Failed to find library with user friendly name $LibraryName"
exit 1
}
foreach ($media in @(Get-Tape -DPMLibrary $library))
{
write-host "Getting media..."
if ($media -is [Microsoft.Internal.EnterpriseStorage.Dls.UI.ObjectModel.LibraryManagement.ArchiveMedia])
{
foreach ($rp in @(Get-RecoveryPoint -Tape $media))
{
write-host "Getting recovery point..."
Get-RecoveryPoint -Datasource $rp.Datasource | Out-Null
Write-Verbose "Removing recovery point created at $($rp.RepresentedPointInTime) for tape in $($media.Location)."
write-host "Force removing recovery point..."
Remove-RecoveryPoint -RecoveryPoint $rp -ForceDeletion -Confirm:$false
}
Write-Verbose "Setting tape in $($media.Location) as free."
write-host "Setting tape as free..."
Set-Tape -Tape $media -Free
}
else
{
Write-Error "The tape in $($media.Location) is a cleaner tape."
}
}
Problem: After making some changes to a server the 2010 Data Protection Manager agent was no longer communicating with the DPM Server.
Solution: Re-installing the agent did not completely fix things. The following command directed the agent to communicate to the DPM Server:
C:\Program Files\Microsoft Data Protection Manager\DPM\bin\ setDPMServer -DPMservername DPMSERVER
Configuring dpm server settings and firewall settings for dpm server =[DPMSERVER]
Configuring dpm server settings and firewall settings for dpm server =[company.com\DPMSERVER]
Configuration completed successfully!!!
This is the manual process for installing the DPM 2010 agent.
Another tip: If the DPM agent will not communicate after a manual install, try the same procedure after disabling the firewall (temporarily).
I encourage trying this even if the Windows firewall statements look correct. In one troublesome instance the DPM client was only able to communicate after I disabled the Windows firewall and ran the
setDPMServer -DPMservername DPMSERVER command. The DPM agent lost its connection after I enabled the firewall again but at least this set me in the right direction!
Feel free to post comments or questions regarding DPM. I'm happy to help!
Last updated November 26th, 2013 by Steven Jordan
*I posted an update to this script
here.
Problem: I wanted to use a DAT 72 tape that previously had data written to it. When trying to free the tape I received the following error:
The selected tapes cannot be erased because they belong to protection groups
Solution: The tape cannot be released via DPM 2010 GUI. I found the following PowerShell script that allowed me to use the tape:
----------------------------- Start of Script --------------------------------
param ([string] $DPMServerName, [string] $LibraryName, [string[]] $TapeLocationList)
if(("-?","-help") -contains $Args[0])
{Write-Host "Usage: ForceFree-Tape.ps1 [[-DPMServerName] ] [-LibraryName] [-TapeLocationList] "Write-Host "Example: Force-FreeTape.ps1 -LibraryName "My library" -TapeLocationList Slot-1, Slot-7"exit 0
}
if (!$DPMServerName)
{$DPMServerName = Read-Host "DPM server name: "if (!$DPMServerName)
{Write-Error "Dpm server name not specified."exit 1
}
}if (!(Connect-DPMServer $DPMServerName))
{Write-Error "Failed to connect To DPM server $DPMServerName"exit 1
}
$library = @(Get-DPMLibrary $DPMServerName )if ($library.count -eq 0)
{Write-Error "Failed to find library with user friendly name $LibraryName"exit 1
}
if (!$LibraryName)
{$library | foreach {$_.userfriendlyname}$LibraryName = Read-Host "Library name (cut & paste from above): "if (!$LibraryName)
{
Write-Error "Library name not specified."exit 1
}
}
if (!$TapeLocationList)
{$tmp = Read-Host "Tape location: "$TapeLocationList=$tmp.split(",")write-host "Processing this slot list..."$TapeLocationListif (!$TapeLocationList)
{Write-Error "Tape location not specified."exit 1
}
}
foreach ($media in @(Get-Tape -DPMLibrary $library))
{if ($TapeLocationList -contains $media.Location)
{if ($media -is [Microsoft.Internal.EnterpriseStorage.Dls.UI.ObjectModel.LibraryManagement.ArchiveMedia])
{foreach ($rp in @(Get-RecoveryPoint -Tape $media))
{Get-RecoveryPoint -Datasource $rp.Datasource | Out-NullWrite-Verbose "Removing recovery point created at $($rp.RepresentedPointInTime) for tape in $($media.Location)."Remove-RecoveryPoint -RecoveryPoint $rp -ForceDeletion -Confirm:$false}
Write-Verbose "Setting tape in $($media.Location) as free."Set-Tape -Tape $media -Free}else{Write-Error "The tape in $($media.Location) is a cleaner tape."}
}
}
----------------------------- End of Script ---------------------------------
Last updated March 26th, 2014 by Steven Jordan
Takeaway: PowerShell script to run the
#consistency check on any every inconsistent replica in DPM.
I plan to schedule and automate this to cut back on the crazy amount of alerts DPM creates. This should also cut down on the manual maintenance.
- Associate the DPM server:
$pg = Get-ProtectionGroup
- Start the consistency check:
foreach ($pgi in $pg) { $ds = get-datasource $pgi; foreach ($dsi in $ds) { if ($dsi.State -eq 'Invalid') { Start-DatasourceConsistencyCheck $dsi | out-null; $dsi.ProductionServerName + " :: " + $dsi.DisplayPath } } }
Reference:
http://www.avianwaves.com/Blog/default.aspx?id=195
O #Scripts #PowerShell O