Как отследить переезд файловых ролей на другой хост кластера

powershell

Добрый день! Уважаемые читатели и гости IT блога Pyatilistnik.org. В минувший раз мы с вами рассмотрели причины и методы устранения черного экрана Windows. Сегодня я хочу с вами поделится полезным PowerShell скриптом, который позволит вам отслеживать переезд файловых ролей на файловом отказоустойчивом кластере Microsoft Windows. Данная задача нужна для того, чтобы средство резервного копирования Veeam Backup могло корректно сделать резервную копию данных, так как если роль переезжает, то могут быть проблемы.

⚒Описание задачи

Как я и указал выше есть файловый кластер построенный на технологиях Windows, по нодам кластера распределены файловые роли. Для того чтобы их бэкапить используется Veeam Backup & Replication 11. Есть небольшая проблема  в его связке с резервным копированием файловых ролей. Если файловая роль переезжает на другую ноду, например при обслуживании сервера (Установка обновлений), то Veeam Backup & Replication вместо дифференциального резервного копирования начинает делать новый полный бэкап, а если у вас диски файловой роли могут весить по 50 ТБ и более, то данный процесс очень сильно замедлит резервное копирование, которое должно стартовать по расписанию. Чтобы этого не допускать, был написан небольшой скрипт PowerShell, который это мониторит и оповещает администратора, что произошло данное событие и желательно вернуть файловую роль на ее законное место.

На выходе я хочу получить вот такое оповещение.

Check File Server Roles Owner in DFSCLUSTER

✅Подписывайте на мой канал для системных администраторов и людей, кто хочет лучше разбираться в компьютерах - https://t.me/pyatilistnikorg

✅И второй канал посвященный чисто PowerShell, я назвал его PowerShell азбука - https://t.me/azbuka_powershell

Вот и сам текст PowerShell скрипта по проверке переезда роли на DFS кластере.

#requires -module ActiveDirectory
#requires -module FailoverClusters
#requires -RunAsAdministrator

#💻Создаем папку для логов если ее нет и будим туда записывать все происходящее
function Date {Get-Date -Format "yyyy.MM.dd HH:mm:ss"}

$log_dir = "$PSScriptRoot\Logs\" + $($MyInvocation.MyCommand.Name -replace (".ps1", ""))
if (! (Test-Path $log_dir -PathType Container -ErrorAction SilentlyContinue))
{
New-Item $log_dir -ItemType D -Force | Out-Null
}

$ClusterGroups_dir = "$log_dir\ClusterGroups"
if (! (Test-Path $ClusterGroups_dir -PathType Container -ErrorAction SilentlyContinue))
{
New-Item $ClusterGroups_dir -ItemType D -Force | Out-Null
}

$log = "$log_dir\" + (Get-Date -Format "yyyy_MM_dd_HH_mm_ss") + ".log"
$ClusterGroups_out = "$ClusterGroups_dir\" + (Get-Date -Format "yyyy_MM_dd_HH_mm_ss") + ".csv"

### 👨‍💻Тело скрипта проверяющего, что роль перемещена

"$(Date) Start Processing" | Tee-Object $log -Append

$cluster = "DFSCLUSTER.pyatilistnik.org"

$ClusterGroups = $null

"$(Date) Fetching Cluster Information" | Tee-Object $log -Append

try {
$ClusterGroups = Get-Cluster $cluster -ErrorAction Stop | Get-ClusterGroup -ErrorAction Stop | ? {$_.GroupType -eq "FileServer"}
}
catch {
"$(Date) $($_.exception.message)" | Tee-Object $log -Append
# Break
}

"$(Date) Exporting data to `"$ClusterGroups_out`" file" | Tee-Object $log -Append
$ClusterGroups | select Name, OwnerNode | Export-Csv $ClusterGroups_out -NoTypeInformation -Encoding Unicode

"$(Date) Trying to compater 2 last results" | Tee-Object $log -Append
$ClusterGroups_out_last2 = $null
$ClusterGroups_out_last2 = (Get-ChildItem $ClusterGroups_dir -File | sort LastWriteTime -Descending | select -First 2 | select -Last 1).FullName

if (! $ClusterGroups_out_last2)
{
"$(Date) Unable to get 2nd file for comparison" | Tee-Object $log -Append
Break
}

"$(Date) Going to compare files: `"$ClusterGroups_out`" and `"$ClusterGroups_out_last2`"" | Tee-Object $log -Append

$ClusterGroups_out_content = $ClusterGroups_out_last2_content = $null
$ClusterGroups_out_content = Import-Csv $ClusterGroups_out
$ClusterGroups_out_last2_content = Import-Csv $ClusterGroups_out_last2

$ClusterGroup_diffs = @()

foreach ($ClusterGroup in $ClusterGroups_out_content)
{
$current_owner = $last_owner = $null

$current_owner = $ClusterGroup.OwnerNode
$last_owner = ($ClusterGroups_out_last2_content | ? {$_.Name -eq $ClusterGroup.Name}).OwnerNode

"$(Date) Current owner - `"$current_owner`", last owner - `"$last_owner`"" | Tee-Object $log -Append

if ($current_owner -ne $last_owner)
{
$ClusterGroup_diff = New-Object PSObject
$ClusterGroup_diff | Add-Member -MemberType NoteProperty -Name "ClusterGroup Name" -Value $ClusterGroup.Name
$ClusterGroup_diff | Add-Member -MemberType NoteProperty -Name "Last Owner Node" -Value $last_owner
$ClusterGroup_diff | Add-Member -MemberType NoteProperty -Name "Current Owner Node" -Value $current_owner

$ClusterGroup_diffs += $ClusterGroup_diff
}
}

### 👩‍💻Формируем отчет в виде таблицы и отправляем его по почте gmail.com

if ($ClusterGroup_diffs)
{
"$(Date) Trying to send notification" | Tee-Object $log -Append

$Header = @"
<style>
TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;}
TD {border-width: 1px; padding: 3px; border-style: solid; border-color: black;}
TH {border-width: 1px; padding: 3px; border-style: solid; border-color: black;}
</style>
"@

$body = $ClusterGroup_diffs | select "ClusterGroup Name", "Last Owner Node", "Current Owner Node" | ConvertTo-Html -Head $Header

$body += "<p>Generated on $($env:COMPUTERNAME + "." + $((Get-WmiObject Win32_ComputerSystem).Domain))"

$from = "support@pyatilistnik.org"
$Subject = "Check File Server Roles Owner in $cluster Cluster"
$smtpserver = "pyatilistnik.org"
$secure = $false
$port = 25 # TLS, for SSL use 465
# $username = "support_user"
# $password = "P@ssw0rd"

$message = New-Object System.Net.Mail.MailMessage
$message.From = $from
$message.To.Add("Адресат-1")
$message.BCC.Add("Адресат-2")
$message.BCC.Add("Адресат-3")
# $message.BCC.Add()

$message.Subject = $Subject
$message.Body = $body
$message.IsBodyHtml = $true

$smtp = New-Object Net.Mail.SmtpClient($smtpserver)

try {
$smtp.Send($message)
}
catch {
"$(Date) $($_.exception.message)" | Tee-Object $log -Append
# Break
}
}
else
{
"$(Date) There are no differences" | Tee-Object $log -Append
}
###

"$(Date) End Processing" | Tee-Object $log -Append

На этом у меня все. Надеюсь, что вам будет полезен данный код. С вами бы Иван Сёмин, автор и создатель IT портала Pyatilistnik.org.

Оцените статью
Настройка серверов windows и linux
Добавить комментарий

  1. Дмитрий

    А зачем мониторить, когда в джобе вима есть pre script.
    Не проще так?

  2. Иван Семин автор

    Это больше для уведомления команды не связанной с СРК