Replacing tape drive assignments - The Official System Center Data Protection Manager Team Blog - Site Home - TechNet Blogs

Replacing tape drive assignments

Replacing tape drive assignments

  • Comments 3
  • Likes

Imagine you got a replacement library for a broken one, or one with larger capacity to partition or share between DPM servers but anyway shows up as another tape drive. For discussion sake we say everything is fine with the new library but you now got all those protection groups on one or more DPM servers pointing to the old library!? You need to re-assign those; protection tab, “Modify protection group” after couple of “Next” to select the new library and commit the change to the group. How many groups and servers did you have? Right, the script below comes to some rescue.

The “DPMswitchTape” script facilitates switching protection groups from using one tape library to another by individually re-assigning the ‘primary backup’ and ‘copy backup’ tape libraries. This script will ask to select source and target libraries and means that only the intended library assignments will change for all protection groups.

The number of drives to assign is kept the same by default and can optionally be specified. If the new drive has not enough drives the script defaults to 1 drive.
Likewise tape options (encryption, compression, data verification) are kept the same and can optionally be changed which will cause the script to ask new values for each group.

Source and target library can be the same which effectively just changes options when used with –ChangeOptions

Note: compression and encryption are mutually exclusive and is also enforced by the script.

Usage: DPMswitchTape.ps1 [-dpmserver <server name>] [-drives #] [-ChangeOptions ]

The script takes the following optional parameters;

  • -dpmservername <server name>, DPM server to manage, uses the local host by default
  • -drives <#>, the number of drives to assign
  • -ChangeOptions switch

Script begin

    [string]$dpmserver = "",

function writelog
    param([string]$msg, $color="Green")
    $msg =  "[{0}] {1}" -f ((get-date).tostring($format)), $msg
    $msg >> $logfile
    Write-Host $msg -ForegroundColor $color
function SelectLibrary
    #get, present and return user selected library
    param([string]$title, $srv)
    # KEEP the where filter, there can be many old libraries definitions no longer present
    $libs = @(Get-DPMLibrary -DPMServerName $srv | where {$_.isoffline -eq $false})
    writelog "`nCurrent online library list..."
    $i = 0
    for ($i = 0; $i -le $libs.count-1; $i ++ ) {
        write-host ("[{0}] {1} ({2} drives, {3} slots)" -f $i,$libs[$i].userfriendlyname, $libs[$i].getdrivecollection().count,$libs[$i].getslotcollection().count)
    [int]$l_index = read-host "`nSelect $title from indexed list  "
    if (!$libs[$l_index]) {Throw "Incorrect selection!"} else {
        $msg = "Selected  -> [" + $libs[$l_index].userfriendlyname + "]"
        writelog $msg
    return $libs[$l_index]
function SetOptions
    # initialize and get library options or keep current
    param ([string]$title, $ChangeOptions, $pg)
    $tp = @{"OnsiteComp"=[boolean]$false; "OnsiteEnc"=[boolean]$false; "OffsiteComp"=[boolean]$false; "OffsiteEnc"=[boolean]$false;"DataVer"=[boolean]$false}
    if ($ChangeOptions) {
        writelog "`nConfigure $title library"
        writelog "WARNING: Encryption and Compression are mutually exclusive, enabling compression disables encryption!`n"
        if ((read-host "Do you want SHORT term protection ENCRYPTION enabled [y/N] ") -imatch "Y") {$tp.item("OnsiteEnc")=$true}
        if ((read-host "Do you want SHORT term protection COMPRESSION enabled [y/N] ") -imatch "Y") {
            if ($tp.item("OnsiteEnc")) { writelog "`t<<< disabling short term encryption >>>"}
        if ((read-host "Do you want LONG  term protection ENCRYPTION enabled [y/N] ") -imatch "Y") {$tp.item("OffsiteEnc")=$true}
        if     ((read-host "Do you want LONG  term protection COMPRESSION enabled [y/N] ") -imatch "Y") {
            if ($tp.item("OffsiteEnc")) { writelog "`t<<< disabling long term encryption >>>"}
        if ((read-host "Do you want to enable backup data verification [y/N] ") -imatch "Y") {$tp.item("DataVer")=$true}
    else {
        $tp.Item("OnsiteComp")    = $pg.ArchiveIntent.OnsiteCompression
        $tp.Item("OnsiteEnc")    = $pg.ArchiveIntent.OnsiteEncryption
        $tp.Item("OffsiteComp")    = $pg.ArchiveIntent.OffsiteCompression
        $tp.Item("OffsiteEnc")    = $pg.ArchiveIntent.OffsiteEncryption
        $tp.Item("DataVer")    = $pg.ArchiveIntent.DatasetVerificationIntent
    return $tp
trap [Exception] {
    # generic trap routine writing to event log and logf file
    writelog "<<< ERROR >>>"
    writelog $("TRAPPED: " + $_.Exception.GetType().FullName);
    #writelog $("TRAPPED: " + $_.Exception.Message);
    writelog "<<< end >>>"
    $log = Get-EventLog -List | Where-Object { $_.Log -eq "Application" }
    $log.Source = "DPMswitchTape"
    $log.WriteEntry("TRAPPED: $error", [system.Diagnostics.EventLogEntryType]::Error,9911)
    exit 1 ;

Disconnect-DPMServer #make sure we have no lingering connections
if ($dpmserver -eq "") {$dpmserver = hostname}
$logfile = "DPMswitchTape.LOG"
$maxlog = 5 * 1024 * 1024
# set some commonly used
$global:format = "HH:mm:ss"
$version = "V2.0"
$c = "`,"; $q = "`'" ; $qq = "`""
if ($drives  -lt 1) {$drives =1}
#set to false for no console output
$Debug = $true

if ($Args.Count -eq 0) {
    writelog "`nUsage: DPMswitchTape.ps1  [-dpmserver <server name>] [-drives #] [-ChangeOptions 0/1]`n"
#display intro
writelog "DPMswitchTape $version using server $dpmserver"
$msg= "`n`tChanges protection group library assignment and options"
$msg= $msg + "`n`t`DPMswitchTape.Ps1 [-DPMserver <servername>]  [-drives #] [-ChangeOptions `$true]`n"
$msg= $msg + "`n`t`Parameter -drives # defaults to previous or 1 drive if target library has less drives than requested"
$msg= $msg + "`n`tSwitch -ChangeOptions `$true indicates you want to change library options, have to specify each group `n"
$msg=$msg + "`n`t(a) Select source of BACKUP and COPY library to be replaced"
$msg=$msg + "`n`t(b) Select target of BACKUP and COPY library to be assigned"
$msg=$msg + "`n`t(c) Select library options (defaults to current definitions)"
$msg=$msg + "`n`t(d) Confirm to modify all groups or exit without changes`n"
writelog $msg "White"

#ensure logfile does not keep growing endlessly
if ((Get-Item $logfile).length -gt $maxlog) {Remove-Item -path $logfile - confirm:$false}

#get backup libs to re-assigned
$sourcelib = SelectLibrary "OLD BACKUP source library to re-assing" $dpmserver
$targetlib = SelectLibrary "NEW BACKUP target library to assign" $dpmserver

#get copy libs to re-assign
$copysourcelib = SelectLibrary "OLD COPY source library to re-assign" $dpmserver
$copytargetlib = SelectLibrary "NEW COPY target library to assign" $dpmserver

if ((read-host "`nContinue and actually modify groups [Y/n] " ) -inotmatch "Y") {
    writelog "Done, exiting without changes!"
    exit 0
writelog "Modifying groups...`n"
$grps = @(Get-ProtectionGroup -DPMServerName $dpmserver | ? {$_.GetDatasources().Count -gt 0})
#Now go modify the groups
foreach ($group in $grps) {
    #skip if not selected source backup library
       if ($group.ArchiveIntent.LibraryId.Equals($sourcelib.Id)) {
           writelog ("Processing group {0}" -f  $group.friendlyname)
        #do library parameters (there is only 1 set of options for both drives)
        $libparams = SetOptions "long term parameters" $ChangeOptions $group
        $libparams >> $logfile
        if  ($targetlib.GetDriveCollection().count -lt $drives) {
            $drives = 1 #possibly set to max available drives instead?
            writelog "Target library has less than requested number of drives, setting drive pool to $drives"
        $mpg=Get-ModifiableProtectionGroup $group
        $mpg.ArchiveIntent.NumberOfDrives= $drives
        Set-ProtectionGroup -ProtectionGroup $mpg
        $msg="Modified BACKUP library of protection group " + $group.FriendlyName + " from [" + $sourcelib.UserFriendlyName + "] to [" + $targetlib.UserFriendlyName + "]"
        writelog $msg
          $msg = "Skipping BACKUP library for protection group " + $group.friendlyname + "  because the curren does not match source selection!"
        writelog $msg
    #skip if not selected source copy library
   if ($group.ArchiveIntent.SecondaryLibraryId.Equals($copysourcelib.Id)) {
        $mpg=Get-ModifiableProtectionGroup $group
        $mpg.ArchiveIntent.NumberOfDrives= $drives
        Set-ProtectionGroup -ProtectionGroup $mpg
        $msg="Modified COPY library of protection group " + $group.FriendlyName + " from [" + $copysourcelib.UserFriendlyName + "] to [" + $copytargetlib.UserFriendlyName + "]"
        writelog $msg
          $msg = "Skipping COPY library for protection group " + $group.friendlyname + "   because the current does not match source selection!"
        writelog $msg
writelog "`nDone!"
exit 0


Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • This assuming the old broken library is online because if it is broken it will show as offline and your script will only query the online library (hint:    $libs = @(Get-DPMLibrary -DPMServerName $srv | where {$_.isoffline -eq $false})

  • Great Script!

    In my case, I needed to replace an offline library for a new one in over 70 protection groups. What I did was replace the line in your script that define the $libs variable:

    original code: $libs = @(Get-DPMLibrary -DPMServerName $srv | where {$_.isoffline -eq $false})
    Replaced with: $libs = @(Get-DPMLibrary -DPMServerName $srv)

    That way, all libraries will be listed for selection, including the offline ones ;)


  • Hi,
    I'm about to replace a tape library on a DPM 2012 installation. Will this script work for 12? Thanks