Скрипт со списком виртуальных машин без бэкапа в Veeam

Обновлено 25.05.2021

veeam logo

Добрый день! Уважаемые читатели и гости одного из крупнейших IT блогов в рунете, посвященных системному администрированию и настройке компьютеров. В прошлый раз мы с вами рассматривали ситуацию с конфликтом IP-адресов на сервере. Идем дальше и в сегодняшнем посте я бы с вами хотел поделиться на мой взгляд полезным скриптом, который будет вас оповещать, какие из виртуальных машин у вас не поставлены на резервное копирование Veeam 10. Возможно, кто-то так же захочет себе организовать данную штуку.

Постановка задачи

И так у меня есть кластер из хостов ESXI, на нем работает свыше 400 виртуальных серверов. Сервера добавляются или удаляются по мере своего рабочего цикла и требуется всегда держать их актуальные резервные копии, так как администраторы всегда должны за этим следить. В качестве системы резервного копирования используется Veeam Backup & Replication 10.

Требуется понять какие виртуальные машины не добавлены в задания по резервному копированию. Для этого я буду сравнивать два массива данных:

  • Полный список виртуальных машин, которые уже добавлены в Veeam Backup & Replication 10 и выполняются
  • Второй, это список виртуальных машин из vCenter
  • Далее все эти данные формируют текстовый файл со списков
  • Так же нужно иметь возможность исключать нужные хосты из данного отчета, так как может не требоваться. Например, нет смысла делать резервную копию всех хостов в RDS ферме, так как они однотипные.
  • Отправка результата по электронной почте

Первый список я буду брать из списка "Jobs - Backup" в Veeam Backup & Replication 10

"Jobs - Backup" в Veeam Backup & Replication 10

Требования

  1. У вас должен быть relay для отправки почты
  2. При желании список виртуальных машин для исключения из отчета
  3. Скрипту нужен модуль VeeamPSSnapin, он ставиться вместе с Veeam Backup & Replication 10 иначе получите ошибку "Add-PSSnapin : The Windows PowerShell snap-in 'VeeamPSSnapIn' is not installed.", но можно до установить и отдельно. Также нужен PowerCLI 10 и выше, как его ставить читайте по ссылке.

VeeamPSSnapin идет в составе дистрибутива, за это отвечает файл BPS_x64.msi.

BPS_x64.msi

Файл со списком серверов, которые не нужно проверять выглядит вот так.

Файл со списком серверов, которые не нужно проверять

PowerShell скрипт для проверки неустановленных на бэкап виртуальных машин

# Добавление VeeamPSSnapin
Add-PSSnapin VeeamPSSnapin

# Файл со списком серверов, которые нужно исключить из сравнения
$Excluded = (Get-Content -Path 'P:\share\SQLBackup\Scripts\Excluded.txt')

$barr_2018 = Get-VBRJob -Name "*2018*" | Get-VBRJobObject | sort name
$barr_620 = Get-VBRJob -Name "*620*" | Get-VBRJobObject | sort name
$barr_CRM = Get-VBRJob -Name "*-CRM*" | Get-VBRJobObject | sort name
$barr_DATALINE = Get-VBRJob -Name "*DATALINE*" | Get-VBRJobObject | sort name
$barr_TST = Get-VBRJob -Name "*-TST*" | Get-VBRJobObject | sort name
$barr_DC = Get-VBRJob -Name "*DC-Virt*" | Get-VBRJobObject | sort name

# Перечисленные массивы из veeam job backup
$barr_2018_h = @()
$barr_620_h = @()
$barr_CRM_h = @()
$barr_DATALINE_h = @()
$barr_TST_h = @()
$barr_DC_h = @()

# Отсюда берутся свойства для массива (имена серверов, их размер)
$barr_2018 | ForEach-Object -Process {
$barr_2018_h += ( New-Object psobject -Property @{"name" = $_.name; "size" = $_.ApproxSizeString; "cluster" = "VBR-barr-2018"} )
}
$barr_620 | ForEach-Object -Process {
$barr_620_h += ( New-Object psobject -Property @{"name" = $_.name; "size" = $_.ApproxSizeString; "cluster" = "VBR-barr-620"} )
}
$barr_CRM | ForEach-Object -Process {
$barr_CRM_h += ( New-Object psobject -Property @{"name" = $_.name; "size" = $_.ApproxSizeString; "cluster" = "VBR-barr-CRM"} )
}
$barr_DATALINE | ForEach-Object -Process {
$barr_DATALINE_h += ( New-Object psobject -Property @{"name" = $_.name; "size" = $_.ApproxSizeString; "cluster" = "VBR-DATALINE"} )
}
$barr_TST | ForEach-Object -Process {
$barr_TST_h += ( New-Object psobject -Property @{"name" = $_.name; "size" = $_.ApproxSizeString; "cluster" = "VBR-TST"} )
}
$barr_DC | ForEach-Object -Process {
$barr_DC_h += ( New-Object psobject -Property @{"name" = $_.name; "size" = $_.ApproxSizeString; "cluster" = "VBR-DC"} )
}

# Массивы из vcenter (
$Veaam_all = @()
$Veaam_all += $barr_2018_h
$Veaam_all += $barr_620_h
$Veaam_all += $barr_CRM_h
$Veaam_all += $barr_DATALINE_h
$Veaam_all += $barr_TST_h
$Veaam_all += $barr_DC_h

$passwordVM = ConvertTo-SecureString '123456' -AsPlainText -Force
$credentialVM = New-Object System.Management.Automation.PSCredential ('veeam@pyatilistnik', $passwordVM)

# Подключение к vCenter серверу
$Connect = (Connect-VIServer -Credential $credentialVM -Server vcenter.pyatilistnik.org -Force)

# Создаем переменную и получаем список всех виртуальных машин (Имя, размер)
$VM_all = (Get-VM | Select-Object -Property Name, @{Name="Size(GB)";Expression={[math]::Ceiling ($_.ProvisionedSpaceGB)}},@{Name=’Cluster’;Expression={$_.VMHost.Parent}}, PowerState | sort name)

$not_backup = @()
$VM_all | ForEach-Object -Process {
if ($Veaam_all.name -contains $_.name) {
}
else {
if ( ($_.cluster -like "BARR-TST") -or ($Excluded -contains $_.name) ) {
}
else {$not_backup += $_}
}
}
$not_backup_count = ($not_backup | measure | select count).count
$Clusters = $VM_all.cluster.name | Select-Object -Unique
$t = "Виртуальные машины, не поставленные на бэкап, в количестве $not_backup_count штук:" | Out-File "P:\share\SQLBackup\Scripts\backups.txt"
$Clusters | ForEach-Object -Process { $not_backup | Where-Object -Property Cluster -like $_ } | Out-File "P:\share\SQLBackup\Scripts\backups.txt" -Append

$deleted = @()
$Veaam_all | ForEach-Object -Process {
if ($VM_all.name -contains $_.name) {
}
else {
if ($Excluded -notcontains $_.name) {
$deleted += $_
}
}
}
$deleted_count = ($deleted | measure | select count).count
$t = "" | Out-File "P:\share\SQLBackup\Scripts\backups.txt" -Append
$t = "Удаленные виртуальные машины, в количестве $deleted_count штук:" | Out-File "P:\share\SQLBackup\Scripts\backups.txt" -Append
$deleted | select name, size, cluster | ft | Out-File "P:\share\SQLBackup\Scripts\backups.txt" -Append

# Тут у меня на vcenter был тестовый кластер, сервера которого я не хочу бэкапить
$TST = @()
$VM_all | ForEach-Object -Process {
if ( ($Veaam_all.name -notcontains $_.name) -and ($_.cluster -like "BARR-TST") -and ($Excluded -notcontains $_.name) ) {
$TST += $_
}
}
$TST_count = ($TST | measure | select count).count
$t = "" | Out-File "P:\share\SQLBackup\Scripts\backups.txt" -Append
$t = "Виртуальные машины кластера BARR-TST, не поставленные на бэкап, в количестве $TST_count штук:" | Out-File "P:\share\SQLBackup\Scripts\backups.txt" -Append
$TST | Out-File "P:\share\SQLBackup\Scripts\backups.txt" -Append

# отключаемся от сервера vCenter
$Connect = (Disconnect-VIServer -Server * -Force -Confirm:$false)

# Подключение к почтовому серверу
$server = "relay.pyatilistnik.org"
$from = "Veeam@pyatilistnik.org"
$to = "Backup-Admins@pyatilistnik.org"
$ssl = $true
$port = 587
$subject = "Список виртуальных машин без бэкапа ( " + $not_backup_count + " : " + $deleted_count + " : " + $TST_count + " )"
$attachment = "P:\share\SQLBackup\Scripts\backups.txt"
$attach = new-object Net.Mail.Attachment($attachment)
$body = $NULL
$body = (Get-Content -Path "P:\share\SQLBackup\Scripts\backups.txt") -join [Environment]::NewLine

$username = "Veeam"
$password = "123456"

# Отправка письма нужным сотрудникам

$SMTPMessage = New-Object System.Net.Mail.MailMessage($from, $to, $subject, $body)
$SMTPMessage.To.Add("semin@pyatilistnik.org")
$SMTPMessage.To.Add("petrov@pyatilistnik.org")
$SMTPMessage.To.Add("ivanov@pyatilistnik.org")
$SMTPMessage.Attachments.Add($attach)
# $SMTPMessage.BodyEncoding = [System.Text.Encoding]::UTF8
# $SMTPMessage.IsBodyHtml = $true
$SMTPClient = New-Object Net.Mail.SmtpClient($server, $port)
$SMTPClient.EnableSsl = $ssl
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($username, $password)
$SMTPClient.Send($SMTPMessage)

$SMTPMessage.Dispose()
$attach.Dispose()

После отработки скрипта у меня, во первых создается локальная копия файла со списком нужных виртуальных серверов.

локальная копия файла со списком нужных виртуальных серверов

И далее приходит письмо с таким же содержанием.

Пример письма со списком сервером, что не поставлены на бэкап

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

Автор - Сёмин Иван

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *