Перейти к содержимому

Как сделать автоматическое назначение тегов бэкапа VMware по типу ОС через PowerCLI

Описание:
Скрипт на PowerShell/PowerCLI для VMware vCenter, который автоматически расставляет теги резервного копирования на виртуальные машины в зависимости от их имени и гостевой ОС. Включённые Windows-ВМ с доменными окончаниями (a.ru, b.ru, d.ru) получают свой отдельный тег бэкапа для каждого заказчика, все прочие включённые Linux-ВМ помечаются общим тегом «Linux Backup», а ВМ с тегом-исключением автоматически лишаются всех тегов бэкапа. Все параметры (адрес vCenter, датацентр, исключаемый кластер, названия тегов и масок имён) вынесены в один блок настроек в начале файла — менять логику скрипта не нужно. Есть встроенный безопасный тестовый режим: перед реальным изменением тегов скрипт может просто показать таблицу с планом действий, ничего не трогая в vCenter. Поддерживается запуск по расписанию (Task Scheduler) без интерактивного ввода, а также ведётся ежедневный лог с автоматическим удалением файлов старше 14 дней.

#===================================================================
#  НАСТРОЙКИ (все переменные скрипта — здесь)
#===================================================================
$Apply = $false   # $false = тестовый режим (без изменений), $true = реальное применение тегов

$vcenter          = "vcsa8.a.ru"
$Datacenter_name  = "Moscow*"
$ExcludedCluster  = "vSAN-CL01"

$LogFolder        = "D:\Programs\Vmware tag\Logs"
$LogRetentionDays = 14

$Taga   = "a Windows Backup"
$Tagb  = "b Windows Backup"
$TagTeex    = "d Windows Backup"
$TagLinux   = "Linux Backup"
$TagExclude = "Exclude BackupVM"

$NameFiltera  = "*a.ru"
$NameFilterb = "*b.ru"
$NameFilterTeex   = "*d.ru"
#===================================================================


#--- Подготовка папки логов и ежедневное имя файла ---
if (-not (Test-Path $LogFolder)) {
    New-Item -Path $LogFolder -ItemType Directory -Force | Out-Null
}
$LogPath = Join-Path $LogFolder ("log_{0}.txt" -f (Get-Date -Format "yyyy-MM-dd"))

#--- Очистка логов старше $LogRetentionDays дней ---
Get-ChildItem -Path $LogFolder -Filter "log_*.txt" -ErrorAction SilentlyContinue |
    Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$LogRetentionDays) } |
    Remove-Item -Force -ErrorAction SilentlyContinue

Start-Transcript -Path $LogPath -Append

Write-Output "==================================================="
Write-Output " Скрипт назначения тегов бэкапа VMware"
Write-Output " Дата запуска: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
Write-Output " vCenter: $vcenter"
if ($Apply) {
    Write-Output " Режим: РЕАЛЬНОЕ ПРИМЕНЕНИЕ (Apply = `$true)"
}
else {
    Write-Output " Режим: ТЕСТ / DRY-RUN (Apply = `$false)"
}
Write-Output "==================================================="
Write-Output ""

try {
    Connect-VIServer $vcenter -ErrorAction Stop
}
catch {
    Write-Error "Не удалось подключиться к $vcenter : $_"
    Stop-Transcript
    return
}

# Собираем список ВМ и тегов ОДИН раз, вместо пяти отдельных запросов
$AllVMs = Get-Datacenter -Name $Datacenter_name |
    Get-Cluster |
    Where-Object { $_.Name -notlike $ExcludedCluster } |
    Get-VM |
    Select-Object Name, PowerState, Guest, @{Name = "Tags"; Expression = { (Get-TagAssignment -Entity $_).Tag.Name } }

$PlannedActions = New-Object System.Collections.Generic.List[Object]

function Add-PlannedAction ($VMName, $Action, $TagName) {
    $PlannedActions.Add([PSCustomObject]@{
        VM     = $VMName
        Action = $Action
        Tag    = $TagName
    })
}

# --- a Windows Backup ---
$FileContent = $AllVMs | Where-Object {
    $_.Name -like $NameFiltera -and
    $_.PowerState -eq "PoweredOn" -and
    $_.Tags -notcontains $Taga -and
    $_.Guest -like "*windows*" -and
    $_.Tags -notcontains $TagExclude
}
foreach ($VMinFile in $FileContent) {
    Add-PlannedAction $VMinFile.Name "Добавить тег" $Taga
    if ($Apply) {
        Get-VM $VMinFile.Name | New-TagAssignment -Tag $Taga
    }
}

# --- b Windows Backup ---
$bvm = $AllVMs | Where-Object {
    $_.Name -like $NameFilterb -and
    $_.PowerState -eq "PoweredOn" -and
    $_.Tags -notcontains $Tagb -and
    $_.Guest -like "*windows*" -and
    $_.Tags -notcontains $TagExclude
}
foreach ($bvms in $bvm) {
    Add-PlannedAction $bvms.Name "Добавить тег" $Tagb
    if ($Apply) {
        Get-VM $bvms.Name | New-TagAssignment -Tag $Tagb
    }
}

# --- d Windows Backup ---
$teexvm = $AllVMs | Where-Object {
    $_.Name -like $NameFilterTeex -and
    $_.PowerState -eq "PoweredOn" -and
    $_.Tags -notcontains $TagTeex -and
    $_.Guest -like "*windows*" -and
    $_.Tags -notcontains $TagExclude
}
foreach ($teexvms in $teexvm) {
    Add-PlannedAction $teexvms.Name "Добавить тег" $TagTeex
    if ($Apply) {
        Get-VM $teexvms.Name | New-TagAssignment -Tag $TagTeex
    }
}

# --- Linux Backup ---
$linuxxvm = $AllVMs | Where-Object {
    $_.PowerState -eq "PoweredOn" -and
    $_.Tags -notcontains $TagLinux -and
    $_.Guest -notlike "*windows*" -and
    $_.Tags -notcontains $TagExclude -and
    $_.Tags -notcontains $TagTeex -and
    $_.Tags -notcontains $Taga
}
foreach ($linuxxvms in $linuxxvm) {
    Add-PlannedAction $linuxxvms.Name "Добавить тег" $TagLinux
    if ($Apply) {
        Get-VM $linuxxvms.Name | New-TagAssignment -Tag $TagLinux
    }
}

# --- Снятие тегов с исключённых ВМ ---
$VMs = $AllVMs | Where-Object {
    $_.Tags -contains $TagExclude -and
    $_.Tags -like "*Backup"
}

if ($null -eq $VMs -or $VMs.Count -eq 0) {
    Write-Output "`nНет ВМ, требующих снятия тегов бэкапа ($TagExclude)."
}
else {
    $BackupTagsToStrip = @($Taga, $Tagb, $TagTeex, $TagLinux)
    foreach ($vmRow in $VMs) {
        foreach ($tagName in $BackupTagsToStrip) {
            if ($vmRow.Tags -contains $tagName) {
                Add-PlannedAction $vmRow.Name "Снять тег" $tagName
            }
        }
    }

    if ($Apply) {
        $VMsFull = Get-VM -Name $VMs.Name
        foreach ($VM in $VMsFull) {
            foreach ($tagName in $BackupTagsToStrip) {
                $VM | Get-TagAssignment -Tag $tagName -ErrorAction SilentlyContinue | Remove-TagAssignment -Confirm:$false
            }
        }
    }
}

# --- Итоговый вывод ---
Write-Output "`n=== Список действий (всего: $($PlannedActions.Count)) ==="
if ($PlannedActions.Count -gt 0) {
    $PlannedActions | Sort-Object Action, VM | Format-Table -AutoSize
}
else {
    Write-Output "Изменений не требуется — все теги уже расставлены корректно."
}

if (-not $Apply -and $PlannedActions.Count -gt 0) {
    Write-Output "`nЭто был тестовый прогон. Изменения не применялись."
}

Stop-Transcript
Disconnect-VIServer $vcenter -Confirm:$false

 

Similar Posts:

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

Яндекс.Метрика