Blog/Backup Exec/tape_check.ps1
2023-12-17 01:18:44 +01:00

279 lines
8.8 KiB
PowerShell

#Script créé par Nicolas Lang - Sous licence CC-BY-SA
#https://nicolaslang.fr
param(
[int]$joursprochains = 0
)
#Ce paramètre vous permettra de choisir sur combien de jours vous souhaitez analyser les sauvegardes
#Le serveur SMTP pour l'envoi du mail
$mailserver = "smtpserver.domain.local"
#L'expéditeur
$from = "moi@domain.local"
#Le / Les destinateurs
$to = @("moi@domain.local","lui@domain.local","eux@autredomaine.fr")
#On démarre un fichier de log, utile en cas de problème
Start-Transcript C:\Temp\BECheck.txt -Force
#On essaie d'importer le module BEMCLI. S'il n'existe pas, alors on arrête le script
try
{
Import-Module BEMCLI
}
catch
{
Write-Output "Impossible d'importer le module BEMCLI"
throw("No BEMCLI")
exit
}
#Un peu de texte pour alimenter le fichier de log
if ($joursprochains -ne 0)
{
Write-Output "$((get-date).tolongtimestring()) : Vérification pour les $joursprochains prochains jours."
}
Write-Output "$((get-date).tolongtimestring()) : Récupération de l'objet de librairie"
#On essaie d'obtenir l'objet de libraire. Si c'est impossible, on coupe.
try
{
$librairie = Get-BERoboticLibraryDevice
}
catch
{
Write-Output "$((get-date).tolongtimestring()) : Impossible de récupérer la libraire : $($Error[0])"
throw("Library error")
exit
}
# On essaie ensuite de récuperer la liste des backups. Si une erreur se présente, on coupe.
try
{
$listofjobs = Get-BEJob -JobType "Backup"
}
catch
{
Write-Output "$((get-date).tolongtimestring()) : Impossible de récuperer les jobs : $($error[0])"
throw("Backup error")
exit
}
#region inventaire
#Lancement d'un inventaire. Si pas d'inventaire... et bien... la aussi, on coupe.
try
{
$inventory = Submit-BEInventoryJob -RoboticLibraryDevice $librairie
}
catch
{
Write-Output "$((get-date).tolongtimestring()) : Une erreur s'est produite durant le lancement de l'inventaire : $($Error[0])"
throw("Inventory error")
exit
}
#Attente du lancement du job d'inventaire
#L'outil BEMCLI est assez mal concu sur certains points. Il y a un décallage entre le lancement de l'inventaire et sa détection dans les jobs actifs.
#Nous devons donc attendre que l'inventaire déclenché précedemment soit détecté et actif.
Write-Output "Attente du lancement du job`n"
do
{
try
{
$jobcheck = Get-BEActiveJobDetail
}
catch
{
Write-host -NoNewline "-"
}
$jobfinished = Get-BEJobHistory -FromStartTime (get-date).Date | Where-Object {$_.name -eq $($inventory.name)}
Start-Sleep -Seconds 10
Write-Host -NoNewline "-"
}
until($jobcheck.Name -eq $inventory.Name -or $jobfinished -ne $null)
Write-host " "
#Couleurs jolies pour patienter. Oui. Comme ça.
$i = 1
$z = 15
Write-Host $(" " * $((get-host).ui.rawui.buffersize.width)) -BackgroundColor 15
Write-Host "Attente de la fin du job d'inventaire"
Write-Host $(" " * $((get-host).ui.rawui.buffersize.width)) -BackgroundColor 15
do {
if ($i % $((get-host).UI.RawUI.BufferSize.Width) -eq 0)
{
if ($z -eq 0){$z = 16}
$z--
Write-host " " -BackgroundColor $z
}
else
{
Write-Host -NoNewline " " -BackgroundColor $z
}
$i++
Start-Sleep -Seconds 1
$endofjob = Get-BEJobHistory -FromStartTime (get-date).Date | Where-Object {$_.name -eq $($inventory.name)}
}while ($endofjob -eq $null)
#Si le job n'est pas en succès, on coupe la et on avertit. Sinon, on continue.
if ($endofjob.JobStatus -ne "Succeeded")
{
Write-Output "$((get-date).tolongtimestring()) : Fin de l'inventaire."
Send-MailMessage -From $from -To $to -SmtpServer $mailserver -Subject "Erreur durant l'inventaire" -Body [string]($endofjob | ConvertTo-Html) -BodyAsHtml
Stop-Transcript
throw("ERREUR DURANT L'INVENTAIRE")
Exit
}
Write-Output "$((get-date).tolongtimestring()) : Fin de l'inventaire."
#endregion
#Récupération du pool de media géré par BE. Nous recalculons à l'aide d'une propriété dynamique la date car elle est au format texte.
#Nous en aurons besoin au format DateTime pour pouvoir faire le tri.
Write-output "$((get-date).tolongtimestring()) : Récupération des médias gérés par BE."
try
{
$mediapool = (get-bemedia) | Select-Object Name,AllocatedDate,@{Name = "Date ajoutable";Expression = {Get-date $_.AppendableUntilDate}} | Sort-Object "date ajoutable" -Descending
}
catch
{
Write-output "$((get-date).tolongtimestring()) : Erreur lors de la récupération du pool de médias : $($error[0])"
}
#Récupération du contenu de l'autoloader.
Write-output "$((get-date).tolongtimestring()) : Récupération du contenu de l'autoloader."
try
{
$slots = Get-BERoboticLibrarySlot -RoboticLibraryDevice $librairie -IsCleaningSlot $false
}
catch
{
Write-output "$((get-date).tolongtimestring()) : Erreur lors de la récupération des slots de la librairie : $($Error[0])"
}
#Récupération des jobs dont le prochain démarrage est entre aujourd'hui et le nombre de jours précisé.
$jobrunningtoday = $listofjobs | Where-Object {($_.nextstartdate.date -ge (get-date).Date -and $_.nextstartdate.date -le (get-date).AddDays($joursprochains).Date)} | Select-Object Name,Storage,nextStartDate
if ($jobrunningtoday -eq $null)
{
Write-output "$((get-date).tolongtimestring()) : Aucune sauvegarde detectée. Fin du script"
throw("No backup")
exit
}
$tapedefinitions = New-Object System.Collections.ArrayList
$validtapes = New-Object System.Collections.ArrayList
$analysed = @()
# Dans la liste des jobs qui seront lancés, nous récupérons l'emplacement utilisé dans la librairie et vérifions le nombre de cassettes sur lequel nous pouvons écrire.
foreach ($job in $jobrunningtoday)
{
if ($job.storage -notin $analysed)
{
$analysed += $job.storage
$slots = Get-BERoboticLibrarySlot -RoboticLibraryPartition $job.storage
foreach ($tape in $slots)
{
try {
$writedate = $($($mediapool | Where-Object {$_.name -eq $tape.media})."date ajoutable" | Sort-Object -Property "date ajoutable" -Descending) | Select-Object -First 1 -ErrorAction Stop
}
catch
{
Write-Host "Pas de date d'écriture sur une cassette"
$writedate = get-date "01/01/2001"
}
$tapedefinitions.Add([PSCUSTOMOBJECT]@{
"Media" = $tape.Media
"Slot" = $tape.SlotNumber
"Storage" = $job.storage
"Ecrasable" = $writedate
}) | Out-Null
}
try
{
$toadd = $($tapedefinitions | Where-Object {$_.storage -eq $job.storage -and $_.ecrasable -lt $job.nextstartdate -and $_.media -and $_.media -ne $null})
foreach ($addit in $toadd)
{
$validtapes.add($addit) | Out-Null
}
}
catch
{
Write-output "$((get-date).tolongtimestring()) : Détection d'une erreur sur l'ajout de $($toadd.media) dans la liste des cassettes valides"
}
}
}
$groupedjobs = $jobrunningtoday | Group-Object Storage
$groupedtapes = $validtapes | Group-Object Storage
$errorarray = New-Object System.Collections.ArrayList
# En fonction de si l'on a le nombre précis de cassettes necessaires pour les sauvegardes (Ex : 2 backups a faire et 2 cassettes à disposition),
# nous affichons un message d'alerte.
# Si c'est un nombre inférieur, nous affichons une erreur
foreach ($line in $groupedjobs)
{
$oktapes = $($groupedtapes | Where-Object {$_.name -eq $line.name})
if ($line.count -gt $oktapes.count)
{
$errorarray.Add([PSCUSTOMOBJECT]@{
"Niveau" = "DANGER"
"Erreur" = "$($line.count) sauvegardes ($($line.Group.name)) dans les logements $($line.name), mais seulement $($oktapes.Count) disponible(s) $($oktapes.group.media)"
})
}
elseif ($line.count -eq $oktapes.count)
{
$errorarray.Add([PSCUSTOMOBJECT]@{
"Niveau" = "Avertissement"
"Erreur" = "Juste assez de cassettes disponibles en écriture dans les logements $($line.name) pour faire la/les sauvegarde(s) $($line.Group.name). Si une sauvegarde demande plus d'une cassette, une sera bloquée en attente de média!"
})
}
}
#Et nous envoyons le mail avec toutes les informations nécessaires
$body = ""
$subject = "Liste des cassettes"
$priority = "Normal"
if ($errorarray.Count -gt 0)
{
$subject = "!!DANGER SUR LES PROCHAINES SAUVEGARDES!!"
$priority = "High"
$body += $errorarray | ConvertTo-Html
$body += "
"*5
}
$choosein = $mediapool | Where-object {$_.name -notin $tapedefinitions.media} | Sort-Object "Date ajoutable"
$body += "Liste des cartouches triées par date d'écrasement
"
$body += $choosein | Select-Object Name,"Date ajoutable" | ConvertTo-Html
Send-MailMessage -SmtpServer $mailserver -From $from -To $to -Body $body -BodyAsHtml -Subject $subject -Encoding UTF8 -Priority $priority
Stop-Transcript