Создание Protection Group на DPM2010 с возможностью записи на ленту (LongTerm Tape) на PowerShell

18.07.2012 - 19:20

В этой заметке я хочу рассказать о тех проблемах, с которыми я столкнулся в процессе написания скрипта по созданию Protection Group.
Protection Group (PG) толком никак не переводится, поэтому буду употреблять именно это название.
Сущность заметки состоит в том, что я хочу предостеречь Вас от ошибок и траты времени, ну и себя, чтобы помнить.
В процессе разбора данной темы, я понял, почему продукт Microsoft System Center Data Protection Manager настолько нелюбим всеми. Абсурда хватило настолько, что до сих пор не могу собрать мысли в единое целое. Ошибок в описании командлетов столько, что это повергло меня в шок, я уже не говорю о том, что отсутствие примеров затрудняло работу и отбивало желание работать далее.
Итак! Суть вопроса состоит в том, чтобы с помощью скрипта PowerShell создать копию БД почтового сервера MS Exchange. Копироваться БД должна на диск с возможностью последующего копирования на ленту. На сервере MS Exchange должен стоять агент DPM.
Приступим!
Для начала, я случайно нашёл по созданию PG для папки с параметром копирования на диск. Осталось перепилить его, делов то (я, наивный, так думал).
Чтобы каждый раз не вписывать имя DPM сервера или не привязывать скрипт к одному какому-то серверу, я нашёл код, который определяет FQDN ПК на котором:

$objIPProperties = [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()
$ServerName = $objIPProperties.HostName + "." + $objIPProperties.DomainName

Сам скрипт был написан в виде функции, я оставилбез изменений. Вызываем функцию с параметрами:
NewPG -DPMServerName $ServerName -ProductionServerName "FQDN Exchange Server" -DataSourceName "DB Name" -ProtectionGroupName "PG Name"

Где:

  • FQDN Exchange Server - FQDN сервера роли MailBox, на котором установлен агент DPM;
  • DB Name - имя базы данных сервера MS Exchange;
  • PG Name - имя PG на DPM сервере.

Описываем функцию с параметрами. Командлет Get-ProductionServer вызывается с where { ($_.machinename,$_.name) -contains $ProductionServerName } для того, чтобы отделить нужный сервер из списка ПК, на которых установлен агент.

function NewPG
{
    param($DPMServerName, $ProductionServerName, $DataSourceName, $ProtectionGroupName)
    write-host "Creating a New Protection Group: $ProtectionGroupName..."
    Write-Host "Getting Production Server: $ProductionServerName from DPM: $DPMServerName"
    $ps = Get-ProductionServer -DPMServerName $DPMServerName | where { ($_.machinename,$_.name) -contains $ProductionServerName }  

Определяем источник копирования. Так как вариантов источников много, фильтруем по имени БД:
    Write-Host "Running Inquiry on PS: $ProductionServerName for datasource $DataSourceName"
    $ds = Get-Datasource -ProductionServer $ps -Inquire | where { ($_.logicalpath,$_.name) -contains $DataSourceName }

Определяем доплнительные параметры,например:

  • New-ProtectionGroup - определение PG, но не создание. Для создания нужно подтверждение, но перед этим, нужно описать все параметры;
  • Add-childDatasource - добавление источника копирования;
  • Set-ProtectionType - устанавливаем тип защиты как на диск, так и на ленту. Вариантов много, можно почитать про стратегии D2D, D2T, D2D2T;

    write-host "Create New PG ..."
    $pg = New-ProtectionGroup -DPMServerName $DPMServerName -Name $ProtectionGroupName
    write-host "Adding child datasource..."
    Add-childDatasource -ProtectionGroup $pg -ChildDatasource $ds
    write-host "Setting Protection Type..."
    Set-ProtectionType -ProtectionGroup $pg -ShortTerm disk -LongTerm tape

Определяем политику и планировщик резервного копирования:

  • Set-PolicyObjective - установка политики резервного копирования, где время актуальности копии = 10 дням. До конца возможностей я не углублялся, но кажется, что второй параметр тоже очень важный Laughing
  • Определяем планировщик резервного копирования. Суть в том, что мы не можем сами создать планировщик с отдельными параметрами, нужно выбрать из списка уже созданных и изменить его значения по времени, даже если типовые нас устраивают Confused Параметром "-ShortTerm" мы определяем тип списка планировщиков, где выбираем нужный нам с помощью фильтра where { $_.JobTypeString -like "Express full" }. Для того, чтобы увидеть полный список, просто введите команду в шел DPM без фильтра Winking можно ужаснуться.
  • Утверждаем выбранный планировщик для нашей PG.

    write-host "Setting Policy Objective ShortTerm...retention range - 10 Days Before Recovery Point"
    Set-PolicyObjective -ProtectionGroup $pg -RetentionRangeInDays 10 -BeforeRecoveryPoint
    write-host "Setting Policy Schedules ..."
    $ShadowCopysch = Get-PolicySchedule -ProtectionGroup $pg -ShortTerm | where { $_.JobTypeString -like "Express full" }
    Set-PolicySchedule -ProtectionGroup $pg -Schedule $ShadowCopysch -DaysOfWeek mo -TimesOfDay 02:00

Определяем разметку диска для резервной копии. Тут я попытался было выкрутиться, попробовать разные параметры, но столкнулся с забавной мелочью, параметр [-AutoGrow] не хотел применяться. Я по разному писал, и -AutoGrow:$True, и -AutoGrow $True, и без доллара, ноработать он не захотел. Принял решение установить по умолчанию Don''t Know
    write-host "Setting Disk Allocation, with optimization (will take a few minutes to complete)"
    Set-DatasourceDiskAllocation -Datasource $ds -ProtectionGroup $pg

Вот тут начинается самое интересное! Для того, чтобы описать копирование на ленту, нужно установить ещё один планировщик и политику (ну это я могу как-то принять). Но трудность в том, что вариант для стратегии LongTerm (возможность копирования на ленту) определяется только одним путём, где нужно указать знакомый нам срок хранения. И задаётся он в виде экземпляра класса "Microsoft.Internal.EnterpriseStorage.Dls.UI.ObjectModel.OMCommon.RetentionRange", который нигде не описан! Вот тут я даже решился создать тему на форуме TechNet, но по прошествию суток никто не ответил. Проблема была решена методом долгого тыкания и подбора.

  • Определяем RetentionRange - $RRange = New-Object -TypeName Microsoft.Internal.EnterpriseStorage.Dls.UI.ObjectModel.OMCommon.RetentionRange -ArgumentList 3,"months";
  • Устанавливаем политику копирования Set-PolicyObjective с параметром "-RetentionRange $RRange" и "-LongTermBackupFrequency Biweekly" (раз в 2 недели);
  • Выбираем список готовых планировщиков для LongTerm;
  • Устанавливаем значение планировщика. Хочу заметить! Если не писать параметры определения времени и дня, намекая, как бы, что нас всё устраивает, то DPM любезно спросит нас об этом принудительно, поэтому укажем и время и дату. Следует, так же, обратить внимание на то, что название параметров определения времени отличается для LongTerm от ShortTerm (для ShortTerm есть буковка s - DaysOfWeek и TimesOfDay)

    Write-Host "Setting Policy Objective LongTerm..."
    $RRange = New-Object -TypeName Microsoft.Internal.EnterpriseStorage.Dls.UI.ObjectModel.OMCommon.RetentionRange -ArgumentList 3,"months"
    Set-PolicyObjective -ProtectionGroup $pg -RetentionRange $RRange -LongTermBackupFrequency Biweekly
    Write-Host "Setting Policy Schedules for LongTerm"
    $ShadowCopysch = Get-PolicySchedule -ProtectionGroup $pg -LongTerm Tape
    Set-PolicySchedule -ProtectionGroup $pg -Schedule $ShadowCopysch[1] -DayOfWeek sa -TimeOfDay 23:00

Определяем параметры библиотеки и ленты. Оказывается, что все параметры определить сразу нельзя, нужно командлет "Set-TapeBackupOption" указывать дважды Confused
    Write-Host "Set Tape Options..."
    $Lib = Get-DPMLibrary -DPMServerName $DPMServerName
    Set-TapeBackupOption -ProtectionGroup $pg -BackupLibrary $Lib -DrivesAllocated 1
    Set-TapeBackupOption -ProtectionGroup $pg -LongTerm -CompressData -PerformIntegritycheck

Определяем время создания резервной копии как "Сейчас!" и подтверждаем создание PG.
    write-host "Setting Replica Creation Method ..."
    Set-ReplicaCreationMethod -ProtectionGroup $pg -NOW
    write-host "Commiting PG"
    Set-ProtectionGroup $pg
 }

После всего описанного абсурда, PG была успешно создана. Теперь я понял, почему DPM-ом никто не пользуется.
Чтобы скрипт был рабочим, нужно соединить все куски кода в один, ничего при этом не было упущено. Вслучае ошибки - пишите, буду рад ответить.

Ваша оценка: Нет Средняя: 2.8 (6 votes)