Esto sincroniza un repositorio en Azure con azcopy, trae el estado de las últimas 24 horas de los offloads de Veeam 12 y muestra algunas estadísticas de los discos rígidos locales. Finalmente envía todos los resultados en un email HTML.
$toSend = "C:\Temp\logFile.txt" $OutStr = "C:\Temp\AzCopyOutput.txt" $src = "C:\Backup\VeeamConfigBackup" $SASURL = "https://...." # comenzar un nuevo archivo y generar un mini header con la fecha y hostname echo '' > $toSend Add-Content $toSend "Reporte generado el $((Get-Date).ToString('dd/MM/yyyy-HH:mm:ss'))" Add-Content $toSend "<br>" hostname >> $toSend # mostrar los resultados de azcopy Add-Content $toSend "<br>" Add-Content $toSend "<h2>Upload VeeamConfigBackup</h2>" Add-Content $toSend "<br>" C:\temp\Tools\azcopy.exe sync $src $SASURL --delete-destination=true > $OutStr # limpiar líneas con el progreso, que contengan el string '0 Done, 0 Failed, 1 Pending'... (así muestra el '1 Done' y posibles errores) (Get-Content $OutStr) | Where-Object { $_ -notmatch '0 Done, 0 Failed, 1 Pending' } | Set-Content $OutStr # transforma los \n en <br> para el html ((Get-Content $OutStr) -join "<br>") >> $toSend # mostrar los resultados de offloads para las últimas 24 horas Add-Content $toSend "<br>" Add-Content $toSend "<h2>Resumen de resultados (24h) Scale-Out Repo Tiering Jobs</h2>" Add-Content $toSend "<br>" Import-Module Veeam.Backup.Powershell Get-VBRBackupSession | ? { ( $_.CreationTime -ge (Get-Date).AddDays(-1) ) -and ( $_.Result -eq "Failed" ) } | Select JobName, JobType, CreationTime, Result, @{Name="BackupSize";Expression={$_.BackupStats.BackupSize}} | Sort CreationTime | Format-Table > "C:\temp\veeamHistory.txt" $sobrOffload = [Veeam.Backup.Model.EDbJobType]::ArchiveBackup [Veeam.Backup.Core.CBackupSession]::GetByTypeAndTimeInterval($sobrOffload,(Get-Date).adddays(-1), (Get-Date).adddays(1)) | ConvertTo-Html -Property CreationTime,Name,Result -Fragment >> $toSend Add-Content $toSend "<br>" # anexar el estado de los discos Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType= 3" | Select-Object DeviceID, @{Name="Size (GB)"; Expression={"{0:N2}" -f ($_.Size / 1GB)}}, @{Name="Free Space (GB)"; Expression={"{0:N2}" -f ($_.FreeSpace / 1GB)}}, @{Name="Free Space (%)"; Expression={"{0:P2}" -f ($_.FreeSpace / $_.Size)}} | ConvertTo-Html -As Table -Fragment -PreContent "<h2>Disk Information</h2>" >> $toSend # configuración del envío del correo $emailFrom = "[email protected]" $subject = "Local2AzStorage & Tiering status" $emailTo = "[email protected]", "[email protected]" $body = Get-Content $toSend | Out-String $smtpServer = "smtp.domain.tld" # acá efectivamente llama a sendmailmsg para hacer el envío Send-MailMessage -From $emailFrom -To $emailTo -Subject $subject -BodyAsHtml $body -SmtpServer $smtpServer
Versión con envío de SendGrid usando Mailosaurr
- sendDailyReport.ps1
$toSend = "C:\Temp\logFile.txt" $OutStr = "C:\Temp\AzCopyLogFile.txt" $src = "C:\Backup\VeeamConfigBackup" $SASURL = "https://container.blob.core.windows.net/................" # comenzar un nuevo archivo y generar un mini header con la fecha y hostname echo '' > $toSend Add-Content $toSend "Reporte generado el $((Get-Date).ToString('dd/MM/yyyy-HH:mm:ss'))" Add-Content $toSend "<br>" hostname >> $toSend # mostrar los resultados de azcopy Add-Content $toSend "<br>" Add-Content $toSend "<h2>Upload VeeamConfigBackup</h2>" Add-Content $toSend "<br>" C:\Tandem\Tools\azcopy.exe sync $src $SASURL --delete-destination=true > $OutStr # limpiar líneas con el progreso, que contengan el string '0 Done, 0 Failed, 1 Pending'... (así muestra el '1 Done' y posibles errores) (Get-Content $OutStr) | Where-Object { $_ -notmatch '0 Done, 0 Failed, 1 Pending' } | Set-Content $OutStr # transforma los \n en <br> para el html ((Get-Content $OutStr) -join "<br>") >> $toSend # mostrar los resultados de offloads para las últimas 24 horas Add-Content $toSend "<br>" Add-Content $toSend "<h2>Resumen de resultados (24h) Scale-Out Repo Tiering Jobs</h2>" Add-Content $toSend "<br>" Import-Module Veeam.Backup.Powershell Get-VBRBackupSession | ? { ( $_.CreationTime -ge (Get-Date).AddDays(-1) ) -and ( $_.Result -eq "Failed" ) } | Select JobName, JobType, CreationTime, Result, @{Name="BackupSize";Expression={$_.BackupStats.BackupSize}} | Sort CreationTime | Format-Table > "C:\temp\veeamHistory.txt" $sobrOffload = [Veeam.Backup.Model.EDbJobType]::ArchiveBackup [Veeam.Backup.Core.CBackupSession]::GetByTypeAndTimeInterval($sobrOffload,(Get-Date).adddays(-1), (Get-Date).adddays(1)) | ConvertTo-Html -Property CreationTime,Name,Result -Fragment >> $toSend Add-Content $toSend "<br>" # anexar el estado de los discos Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType= 3" | Select-Object DeviceID, @{Name="Size (GB)"; Expression={"{0:N2}" -f ($_.Size / 1GB)}}, @{Name="Free Space (GB)"; Expression={"{0:N2}" -f ($_.FreeSpace / 1GB)}}, @{Name="Free Space (%)"; Expression={"{0:P2}" -f ($_.FreeSpace / $_.Size)}} | ConvertTo-Html -As Table -Fragment -PreContent "<h2>Disk Information</h2>" >> $toSend # mostrar el estado del SOBR Add-Content $toSend "<br>" Add-Content $toSend "<h2>Resumen de estado del repositorio Scale-Out</h2>" Add-Content $toSend "<br>" $sobrs = Get-VBRBackupRepository -Scaleout foreach ($sobr in $sobrs) { $extents = $sobr.Extent foreach ($extent in $extents) { $repo = $extent.Repository $container = $repo.GetContainer() $usagePercentage = [Math]::Round(($container.CachedFreeSpace / $container.CachedTotalSpace) * 100) $output = [PSCustomObject]@{ RepositoryName = $repo.Name CachedTotalSpace = $container.CachedTotalSpace CachedFreeSpace = $container.CachedFreeSpace UsagePercentage = $usagePercentage } $output | ConvertTo-Html -As Table >> $toSend } } # configuración del envío del correo # Import the module Import-Module Mailozaurr # Set the API key and other parameters $apiKey = "SG.____________________API KEY____________________" $from = "[email protected]" $to = "[email protected]" $subject = "AzCopy && Tiering Status 📧" $body = Get-Content $toSend | Out-String # Send the email Send-EmailMessage -From $from -To $to ` -Username 'apikey' ` -Server 'smtp.sendgrid.net' ` -Password $apiKey ` -Body $body ` -DeliveryNotificationOption OnSuccess ` -Priority High -Subject $subject -UseSsl -Port 587 -Verbose
Versión 2023.11
This PowerShell script automates and generates a daily report for Veeam Backup activities, providing valuable insights into recent backup sessions, Azure repository sync status, and the health of local disks and Scale-Out Backup Repositories (SOBR). The script initiates a sync operation using AzCopy to transfer a configuration backup file to an Azure repository, capturing and analyzing the output for potential issues. Additionally, it compiles a summary of Veeam backup job results from the last 24 hours, intelligently truncating lengthy job names for better email formatting. The report includes information on local disk states and the status of Scale-Out Backup Repositories, offering a comprehensive overview of the Veeam environment. The script concludes by sending an email report with the gathered information, and if any issues are detected, a warning sign is appended to the email subject.
- dailyReports.ps1
$toSend = "C:\Temp\logFile.txt" $OutStr = "C:\Temp\AzCopyLogFile.txt" $src = "C:\Backup\VeeamConfigBackup" $SASURL = "https://xxxxx.blob.core.windows.net/...." $subject = "Veeam Daily Report" $last24h = "C:\temp\veeamHistory.txt" # comenzar un nuevo archivo y generar un mini header con la fecha y hostname echo '' > $toSend Add-Content $toSend "Reporte generado el $((Get-Date).ToString('dd/MM/yyyy-HH:mm:ss')) en $env:COMPUTERNAME" Add-Content $toSend "<br>" # mostrar los resultados de azcopy Add-Content $toSend "<br>" Add-Content $toSend "<h2>Copia del archivo .bco al repositorio de Azure</h2>" Add-Content $toSend "<pre>" C:\temp\azcopy.exe sync $src $SASURL --delete-destination=true 2>&1 | Where-Object { $_ -notmatch '0 Done, 0 Failed, 1 Pending' } | Out-File -FilePath $toSend -Append Add-Content $toSend "</pre>" # Si falló, inserta un signo de atención en el asunto del email if ((Get-Content $OutStr) -match '1 Failed') { $subject += " ⚠️" } # mostrar los resultados de jobs para las últimas 24 horas, para tareas que se reintentaron, mostrar el último resultado Add-Content $toSend "<br>" Add-Content $toSend "<h2>Resumen de resultados (últimas 24h)</h2>" Add-Content $toSend "<br>" Import-Module Veeam.Backup.Powershell # Get-VBRBackupSession $backupSessions = Get-VBRBackupSession | Where-Object { $_.CreationTime -ge (Get-Date).AddDays(-1) } | Sort-Object CreationTime # Limit JobName to 12 characters and append '...' $backupSessions = $backupSessions | ForEach-Object { $modifiedJobName = $_.JobName.Substring(0, [Math]::Min($_.JobName.Length, 12)) if ($_.JobName.Length -gt 12) { $modifiedJobName += '...' } [PSCustomObject]@{ JobName = $modifiedJobName CreationTime = $_.CreationTime Result = $_.Result } } $backupSessions | Group-Object JobName | ForEach-Object { $_.Group[0] } | Format-Table > $last24h Add-Content $last24h "</pre><h3>Scale-Out Offloads</h3><pre>" # [Veeam.Backup.Core.CBackupSession]::GetByTypeAndTimeInterval $sobrOffload = [Veeam.Backup.Model.EDbJobType]::ArchiveBackup $offloadSessions = [Veeam.Backup.Core.CBackupSession]::GetByTypeAndTimeInterval($sobrOffload,(Get-Date).adddays(-1), (Get-Date).adddays(1)) | Sort-Object EndTime # Limit JobName to 12 characters and append '...' $offloadSessions = $offloadSessions | ForEach-Object { $modifiedJobName = $_.JobName.Substring(0, [Math]::Min($_.JobName.Length, 12)) if ($_.JobName.Length -gt 12) { $modifiedJobName += '...' } [PSCustomObject]@{ JobName = $modifiedJobName EndTime = $_.EndTime Result = $_.Result } } $offloadSessions | Group-Object JobName | ForEach-Object { $_.Group[0] } | Format-Table >> $last24h # Append the contents of a text file to the variable $toSend Add-Content $toSend "<pre>" Add-Content -Path $toSend -Value (Get-Content $last24h) Add-Content $toSend "</pre>" if ((Get-Content $last24h) -match 'Failed' -or (Get-Content $last24h) -match 'None') { $subject += " ⚠️" } # anexar el estado de los discos locales Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType= 3" | Select-Object DeviceID, @{Name="Size (GB)"; Expression={"{0:N2}" -f ($_.Size / 1GB)}}, @{Name="Free Space (GB)"; Expression={"{0:N2}" -f ($_.FreeSpace / 1GB)}}, @{Name="Free Space (%)"; Expression={"{0:P2}" -f ($_.FreeSpace / $_.Size)}} | ConvertTo-Html -As Table -Fragment -PreContent "<h2>Discos locales</h2>" >> $toSend # mostrar el estado del SOBR Add-Content $toSend "<br>" Add-Content $toSend "<h2>Estado del repositorio Scale-Out</h2>" Add-Content $toSend "<br>" $sobrs = Get-VBRBackupRepository -Scaleout foreach ($sobr in $sobrs) { $extents = $sobr.Extent foreach ($extent in $extents) { $repo = $extent.Repository $container = $repo.GetContainer() $freePercentage = [Math]::Round(($container.CachedFreeSpace / $container.CachedTotalSpace) * 100) $output = [PSCustomObject]@{ RepositoryName = $repo.Name CachedTotalSpace = $container.CachedTotalSpace CachedFreeSpace = $container.CachedFreeSpace FreePercentage = $freePercentage } $output | ConvertTo-Html -As Table >> $toSend } } # configuración del envío del correo $emailFrom = "[email protected]" $emailTo = "[email protected]" $body = Get-Content $toSend | Out-String $smtpServer = "smtp.my.org" # acá efectivamente llama a sendmailmsg para hacer el envío Send-MailMessage -From $emailFrom -To $emailTo -Subject $subject -BodyAsHtml -Body $body -SmtpServer $smtpServer -Encoding ([System.Text.Encoding]::UTF8)
