Выполняется данная настройка в vCenter->Settings->General->Edit->Database. Там необходимо увеличить значение "Event retention (days)" и перегрузить vCenter сервер для применения параметров.
Ниже приведен сам скрипт, который работает следующим образом: по каждой виртуальной машине из указанной папки и подпапок находит последнее событие из двух типов (VmAcquiredTicketEvent, VmAcquiredMksTicketEvent) и пишет одну строку в отчёт.
<#
.SYNOPSIS
Последнее подключение к консоли по каждой ВМ из папки vCenter (VMRC + HTML5).
.DESCRIPTION
Рекурсивно собирает ВМ из указанной папки, находит последнее событие
VmAcquiredTicketEvent или VmAcquiredMksTicketEvent по каждой ВМ
и сохраняет отчёт в .xls (SpreadsheetML) без внешних модулей.
#>
# ======================== НАСТРОЙКИ ========================
$vCenterServer = "vcenter.mydomain.local"
$FolderName = "VM_Folder"
$Days = 360
$OutputPath = Join-Path -Path $PSScriptRoot -ChildPath "vm_console_last_event.xls"
# ==========================================================
$eventTypes = @("VmAcquiredTicketEvent", "VmAcquiredMksTicketEvent")
$startTime = (Get-Date).AddDays(-$Days)
$finishTime = Get-Date
function Get-VMsRecursive {
param($Folder)
$vms = @(Get-VM -Location $Folder -ErrorAction SilentlyContinue)
foreach ($sub in @(Get-Folder -Location $Folder -ErrorAction SilentlyContinue)) {
$vms += Get-VMsRecursive -Folder $sub
}
return $vms
}
function ConvertTo-XmlSafe {
param([string]$s)
if ($null -eq $s) { return "" }
return $s.Replace("&","&").Replace("<","<").Replace(">",">").Replace('"',""").Replace("'","'")
}
function Export-ToSpreadsheetML {
param([object[]]$Rows, [string]$Path, [string]$Title)
$columns = @(
@{ Name = 'ВМ'; Width = 200 },
@{ Name = 'Пользователь'; Width = 160 },
@{ Name = 'Время последнего подключения'; Width = 170 },
@{ Name = 'Сообщение'; Width = 500 }
)
$sb = New-Object System.Text.StringBuilder
[void]$sb.AppendLine('<?xml version="1.0" encoding="UTF-8"?>')
[void]$sb.AppendLine('<?mso-application progid="Excel.Sheet"?>')
[void]$sb.AppendLine('<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"')
[void]$sb.AppendLine(' xmlns:o="urn:schemas-microsoft-com:office:office"')
[void]$sb.AppendLine(' xmlns:x="urn:schemas-microsoft-com:office:excel"')
[void]$sb.AppendLine(' xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">')
[void]$sb.AppendLine(@'
<Styles>
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Top"/>
<Font ss:FontName="Calibri" ss:Size="11"/>
</Style>
<Style ss:ID="Header">
<Alignment ss:Vertical="Center" ss:Horizontal="Center" ss:WrapText="1"/>
<Font ss:FontName="Calibri" ss:Size="11" ss:Bold="1" ss:Color="#FFFFFF"/>
<Interior ss:Color="#4472C4" ss:Pattern="Solid"/>
</Style>
<Style ss:ID="CellWrap">
<Alignment ss:Vertical="Top" ss:WrapText="1"/>
<Font ss:FontName="Calibri" ss:Size="11"/>
</Style>
<Style ss:ID="CellNoEvent">
<Font ss:FontName="Calibri" ss:Size="11" ss:Color="#C00000" ss:Italic="1"/>
</Style>
<Style ss:ID="Title">
<Font ss:FontName="Calibri" ss:Size="12" ss:Bold="1" ss:Color="#1F3864"/>
</Style>
</Styles>
'@)
[void]$sb.AppendLine(' <Worksheet ss:Name="Console_Connections">')
[void]$sb.AppendLine(' <Table>')
foreach ($c in $columns) { [void]$sb.AppendLine(" <Column ss:Width=`"$($c.Width)`"/>") }
$rowNum = 1
if ($Title) {
[void]$sb.AppendLine(" <Row ss:Height=`"22`"><Cell ss:StyleID=`"Title`" ss:MergeAcross=`"$($columns.Count - 1)`"><Data ss:Type=`"String`">$(ConvertTo-XmlSafe $Title)</Data></Cell></Row>")
[void]$sb.AppendLine(' <Row/>')
$rowNum += 2
}
[void]$sb.AppendLine(' <Row ss:Height="28">')
foreach ($c in $columns) { [void]$sb.AppendLine(" <Cell ss:StyleID=`"Header`"><Data ss:Type=`"String`">$(ConvertTo-XmlSafe $c.Name)</Data></Cell>") }
[void]$sb.AppendLine(' </Row>')
$headerRow = $rowNum++
foreach ($r in $Rows) {
$style = if ($r.'Время последнего подключения' -eq '-') { "CellNoEvent" } else { "CellWrap" }
[void]$sb.AppendLine(' <Row>')
foreach ($c in $columns) { [void]$sb.AppendLine(" <Cell ss:StyleID=`"$style`"><Data ss:Type=`"String`">$(ConvertTo-XmlSafe ([string]$r.($c.Name)))</Data></Cell>") }
[void]$sb.AppendLine(' </Row>')
$rowNum++
}
[void]$sb.AppendLine(' </Table>')
[void]$sb.AppendLine(" <AutoFilter x:Range=`"R${headerRow}C1:R$($rowNum - 1)C$($columns.Count)`" xmlns=`"urn:schemas-microsoft-com:office:excel`"/>")
[void]$sb.AppendLine(' <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">')
[void]$sb.AppendLine(' <FreezePanes/><FrozenNoSplit/>')
[void]$sb.AppendLine(" <SplitHorizontal>$headerRow</SplitHorizontal><TopRowBottomPane>$headerRow</TopRowBottomPane><ActivePane>2</ActivePane>")
[void]$sb.AppendLine(' </WorksheetOptions>')
[void]$sb.AppendLine(' </Worksheet>')
[void]$sb.AppendLine('</Workbook>')
$sb.ToString() | Out-File -FilePath $Path -Encoding UTF8
}
# --- Подключение ---
Write-Host "Подключение к $vCenterServer..." -ForegroundColor Cyan
try { Connect-VIServer -Server $vCenterServer -ErrorAction Stop | Out-Null }
catch { Write-Error "Не удалось подключиться: $($_.Exception.Message)"; return }
try {
$folder = @(Get-Folder -Name $FolderName -Type VM -ErrorAction SilentlyContinue)[0]
if (-not $folder) {
Write-Error "Папка '$FolderName' не найдена."
Get-Folder -Type VM | Select-Object Name, Id | Format-Table -AutoSize | Out-Host
return
}
Write-Host "Папка: $($folder.Name) | Период: $($startTime.ToString('yyyy-MM-dd')) — $($finishTime.ToString('yyyy-MM-dd'))" -ForegroundColor Green
$vms = Get-VMsRecursive -Folder $folder | Group-Object Id | ForEach-Object { $_.Group[0] }
if ($vms.Count -eq 0) { Write-Host "ВМ не найдено." -ForegroundColor Yellow; return }
Write-Host "Найдено ВМ: $($vms.Count)`n" -ForegroundColor Green
$rows = New-Object System.Collections.Generic.List[object]
$i = 0
foreach ($vm in $vms) {
$i++
Write-Progress -Activity "Обработка ВМ" -Status "$($vm.Name) ($i из $($vms.Count))" -PercentComplete (($i / $vms.Count) * 100)
try {
$last = Get-VIEvent -Entity $vm -Start $startTime -Finish $finishTime -ErrorAction Stop |
Where-Object { $eventTypes -contains $_.GetType().Name } |
Sort-Object CreatedTime -Descending |
Select-Object -First 1
}
catch {
$rows.Add([PSCustomObject]@{
'ВМ' = $vm.Name; 'Пользователь' = '-'
'Время последнего подключения' = 'Ошибка'
'Сообщение' = $_.Exception.Message
})
continue
}
if ($last) {
$rows.Add([PSCustomObject]@{
'ВМ' = $vm.Name
'Пользователь' = if ($last.UserName) { $last.UserName } else { '-' }
'Время последнего подключения' = $last.CreatedTime.ToString('yyyy-MM-dd HH:mm:ss')
'Сообщение' = [string]$last.FullFormattedMessage
})
}
else {
$rows.Add([PSCustomObject]@{
'ВМ' = $vm.Name
'Пользователь' = '-'
'Время последнего подключения' = '-'
'Сообщение' = 'Нет событий подключений'
})
}
}
Write-Progress -Activity "Обработка ВМ" -Completed
$outDir = Split-Path -Parent $OutputPath
if ($outDir -and -not (Test-Path $outDir)) { New-Item -ItemType Directory -Path $outDir -Force | Out-Null }
$title = "Последнее подключение к консоли — vCenter: $vCenterServer, папка: '$FolderName', период: $($startTime.ToString('yyyy-MM-dd')) — $($finishTime.ToString('yyyy-MM-dd'))"
Export-ToSpreadsheetML -Rows $rows -Path $OutputPath -Title $title
$withEvents = @($rows | Where-Object { $_.'Время последнего подключения' -ne '-' }).Count
Write-Host "`nГотово. ВМ: $($vms.Count), с подключениями: $withEvents, без: $($vms.Count - $withEvents)" -ForegroundColor Green
Write-Host "Файл: $OutputPath" -ForegroundColor Green
}
finally {
Disconnect-VIServer -Server $vCenterServer -Confirm:$false -ErrorAction SilentlyContinue | Out-Null
}
Комментариев нет:
Отправить комментарий