Advertisement
vPowerCLI

vPC Army Report 1.1.Custom

Mar 26th, 2013
2,082
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. asnp "VeeamPSSnapIn" -ErrorAction SilentlyContinue
  2.  
  3. #region User-Variables
  4. # Print job lines
  5. $jlines = $true
  6. # File Output path and filename
  7. $file = "C:\Scripts\Test.htm"
  8. ###############################
  9. # report mode, valid modes
  10. # 24, 48, "Weekly", "Monthly"
  11. $reportMode = 24
  12. # Email configuration
  13. $sendEmail = 0
  14. $emailHost = "smtp.lab.local"
  15. $emailUser = "Veeam(at)lab.local"
  16. $emailPass = "MyPass"
  17. $emailFrom = "Veeam(at)lab.local"
  18. $emailTo = "john.doe(at)lab.local"
  19. #####################
  20. #endregion
  21.  
  22. #region VersionInfo
  23. $vPCARversion = 1.1
  24. #
  25. # Version 1.1
  26. # Added job lines as per a request on the website
  27. #
  28. # Version 1.0
  29. # Clean up for release
  30. #
  31. # Version 0.9
  32. # More cmdlet rewrite to improve perfomace, credit to @SethBartlett
  33. # for practically writing the Get-vPCRepoInfo
  34. #
  35. # Version 0.8
  36. # Added Read/Write stats for proxies at requests of @bsousapt
  37. # Performance improvement of proxy tear down due to rewrite of cmdlet
  38. # Replaced 2 other functions
  39. # Added Warning counter, .00 to all storage returns and fetch credentials for
  40. # remote WinLocal repos
  41. #
  42. # Version 0.7
  43. # Added Utilisation(Get-vPCDailyProxyUsage) and Modes 24, 48, Weekly, and Monthly
  44. # Minor performance tweaks
  45.  
  46. #endregion
  47.  
  48. #region NonUser-Variables
  49. # Get the B&R Server
  50. $vbrServer = Get-VBRLocalHost
  51. # Get all the VI proxies in your army
  52. $viProxyList = Get-VBRViProxy
  53. # Get all the HV proxies in your army
  54. #$hvProxyList = Get-VBRHvProxy
  55. # Get all the backup repositories
  56. $repoList = Get-VBRBackupRepository
  57. # Get all the backup sessions for mode
  58. if ($reportMode -eq "Monthly") {
  59.     $seshList = Get-VBRBackupSession | ?{($_.CreationTime -ge (Get-Date).AddMonths(-1)) -and ($_.State -ne "Working")}
  60. } elseif ($reportMode -eq "Weekly") {
  61.     $seshList = Get-VBRBackupSession | ?{($_.CreationTime -ge (Get-Date).AddDays(-7)) -and ($_.State -ne "Working")}
  62. } elseif ($reportMode -eq 48) {
  63.     $seshList = Get-VBRBackupSession | ?{($_.CreationTime -ge (Get-Date).AddHours(-48)) -and ($_.State -ne "Working")}
  64. } else {
  65.     $seshList = Get-VBRBackupSession | ?{($_.CreationTime -ge (Get-Date).AddHours(-24)) -and ($_.State -ne "Working")}
  66. }
  67.  
  68. if (($reportMode -eq 24) -or ($reportMode -eq 48)) {
  69.     $emailSubject = "vPowerCLI v6 Army Report ($reportMode Hrs)"
  70. } else {
  71.     $emailSubject = "vPowerCLI v6 Army Report ($reportMode)"
  72. }
  73.  
  74. #Get replica jobs
  75. $repList = Get-VBRJob | ?{$_.IsReplica}
  76. $global:vPCRTArray = @() #HT Used to track returned datastores
  77. # Get the job counts
  78. $totalJobCount = @($seshList)
  79. $succesJobCount = @($seshList | ?{$_.Result -eq "Success"})
  80. $warningJobCount = @($seshList | ?{$_.Result -eq "Warning"})
  81. $failedJobCount = @($seshList | ?{$_.Result -eq "Failed"})
  82. #endregion
  83.  
  84. #region Functions
  85.  
  86. function Get-vPCProxyInfo {
  87. [CmdletBinding()]
  88.     param (
  89.         [Parameter(Position=0)]
  90.         [String[]]$Name,
  91.        
  92.         [Parameter(Mandatory=$true, Position=1)]
  93.         [PSObject[]]$Sessions
  94.     )
  95.     Begin {
  96.         $vPCObjAry = @()
  97.         [Int]$script:jobcount = 0
  98.         [Int]$totalObjInJob = 0
  99.         $cleanSessions = $Sessions | ?{($_.Result -ne "Failed") -and
  100.             ($_.State -eq "Stopped") -and ($_.JobType -ne "Copy")}
  101.         $cleanSessions | %{$totalObjInJob = $totalObjInJob + $_.Progress.TotalObjects} |
  102.             Out-Null
  103.    
  104.         function Build-vPCObj {param ([PsObject]$inputObj)
  105.             $ping = new-object system.net.networkinformation.ping
  106.             $pinginfo = $ping.send("$($inputObj.Host.RealName)")
  107.            
  108.             if ($pinginfo.Status -eq "Success") {
  109.                 $hostAlive = "Alive"
  110.             } else {
  111.                 $hostAlive = "Dead"
  112.             }
  113.            
  114.             $vPCFuncObject = New-Object PSObject -Property @{
  115.                 ProxyName = $inputObj.Name
  116.                 RealName = $inputObj.Host.RealName.ToLower()
  117.                 Disabled = $inputObj.IsDisabled
  118.                 Status  = $hostAlive
  119.                 IP = $pinginfo.Address
  120.                 Responce = $pinginfo.RoundtripTime
  121.                 ReadData = [Decimal]0.00
  122.                 WriteData = [Decimal]0.00
  123.                 UsageCount = 0
  124.                 ProxiesInSessions = $($totalObjInJob*2)
  125.             }
  126.             return $vPCFuncObject
  127.         }
  128.        
  129.         function Get-vPCProxyName {param ([String]$title)
  130.             $titleAry = @($title.Split())
  131.             $ai = 3
  132.             $bi = $titleAry.count - 1
  133.            
  134.             while ($ai -ne $bi) {
  135.                 $proxyString = $proxyString + " " + $titleAry[$ai]
  136.                 $ai ++
  137.             }
  138.             return $proxyString.Trim()
  139.         }
  140.        
  141.         function Get-vPCProxyRole {param ([String]$title)
  142.             $titleAry = @($title.Split())
  143.             $roleString = $titleAry[1]
  144.             return $roleString
  145.         }
  146.         Get-VBRViProxy | %{$vPCObjAry = $vPCObjAry + $(Build-vPCObj $_)}
  147.     }
  148.     Process {
  149.         foreach ($session in $cleanSessions) {
  150.             [Int]$vms = $session.Progress.TotalObjects
  151.             [Int]$i = 0
  152.             while ($i -lt $vms) {
  153.                 $vmTask = $session.GetTaskSessions()[$i]
  154.                 $readData = $vmTask.info.progress.readsize/1GB
  155.                 $writeData = $vmTask.info.progress.storedsize/1GB
  156.                 $vmTaskLog = $vmTask.Logger.GetLog()
  157.                 $proxies = @($vmTaskLog.UpdatedRecords | ?{($_.Title -like "Using source proxy*") -or
  158.                     ($_.Title -like "Using target proxy*")})
  159.                                                
  160.                 # Update Values
  161.                 if ($proxies.Count -eq 2) {
  162.                     foreach ($proxy in $proxies) {
  163.                         $udProxy = $vPCObjAry | ?{$_.ProxyName -eq $(Get-vPCProxyName $proxy.Title)}
  164.                         $udProxy.UsageCount ++
  165.                         $role = Get-vPCProxyRole $proxy.Title
  166.                                
  167.                         if ($role -eq "source") {
  168.                             $udProxy.ReadData = [Math]::Round(([Decimal]$udProxy.ReadData + $readData),2)
  169.                         }
  170.                         elseif ($role -eq "target") {
  171.                             $udProxy.WriteData  = [Math]::Round(([Decimal]$udProxy.WriteData + $writeData), 2)
  172.                         }
  173.                     }
  174.                 }
  175.                 elseif ($proxies.Count -eq 1) {
  176.                     foreach ($proxy in $proxies) {
  177.                         $udProxy = $vPCObjAry | ?{$_.ProxyName -eq $(Get-vPCProxyName $proxy.Title)}
  178.                         $udProxy.UsageCount += 2
  179.                                                                    
  180.                         $udProxy.ReadData = [Math]::Round(([Decimal]$udProxy.ReadData + $readData),2)
  181.                         $udProxy.WriteData  = [Math]::Round(([Decimal]$udProxy.WriteData + $writeData),2)
  182.                     }
  183.                 }
  184.                 $i ++
  185.             }
  186.         }
  187.         if ($Name -ne $null) {
  188.             $output = $vPCObjAry | ?{$Name -like $_.ProxyName}
  189.         }
  190.         else {
  191.             $output = $vPCObjAry
  192.         }
  193.     }
  194.     End {
  195.         foreach ($obj in $output) {
  196.             $obj | Add-Member Noteproperty Util $([Math]::Round(($obj.UsageCount/$obj.ProxiesInSessions)*100))
  197.         }
  198.         $output
  199.     }
  200. }
  201.  
  202. function Get-vPCRepoInfo {
  203. [CmdletBinding()]
  204.     param (
  205.         [Parameter(Position=0, ValueFromPipeline=$true)]
  206.         [PSObject[]]$Repository
  207.         )
  208.     Begin {
  209.         $outputAry = @()
  210.         [Reflection.Assembly]::LoadFile("C:\Program Files\Veeam\Backup and Replication\Veeam.Backup.Common.dll") | Out-Null
  211.         function Build-Object {param($name, $path, $free, $total)
  212.             $repoObj = New-Object -TypeName PSObject -Property @{
  213.                     Target = $name
  214.                     Storepath = $path
  215.                     StorageFree = [Math]::Round([Decimal]$free/1GB,2)
  216.                     StorageTotal = [Math]::Round([Decimal]$total/1GB,2)
  217.                     FreePercentage = [Math]::Round(($free/$total)*100)
  218.                 }
  219.             return $repoObj | Select Target, Storepath, StorageFree, StorageTotal, FreePercentage
  220.         }
  221.     }
  222.     Process {
  223.         foreach ($r in $Repository) {
  224.             if ($r.GetType().Name -eq [String]) {
  225.                 $r = Get-VBRBackupRepository -Name $r
  226.             }
  227.             if ($r.Type -eq "WinLocal") {
  228.                 $Server = $r.GetHost()
  229.                 $FileCommander = [Veeam.Backup.Core.CRemoteWinFileCommander]::Create($Server.Info)
  230.                 $storage = $FileCommander.GetDrives([ref]$null) | ?{$_.Name -eq $r.Path.Substring(0,3)}
  231.                 $outputObj = Build-Object $r.Name $r.Path $storage.FreeSpace $storage.TotalSpace
  232.             }
  233.             elseif ($r.Type -eq "LinuxLocal") {
  234.                 $Server = $r.GetHost()
  235.                 $FileCommander = new-object Veeam.Backup.Core.CSshFileCommander $server.info
  236.                 $storage = $FileCommander.FindDirInfo($r.Path)
  237.                 $outputObj = Build-Object $r.Name $r.Path $storage.FreeSpace $storage.TotalSize
  238.             }
  239.             elseif ($r.Type -eq "CifsShare") {
  240.                 $fso = New-Object -Com Scripting.FileSystemObject
  241.                 $storage = $fso.GetDrive($r.Path)
  242.                 $outputObj = Build-Object $r.Name $r.Path $storage.AvailableSpace $storage.TotalSize
  243.             }
  244.             $outputAry = $outputAry + $outputObj
  245.         }
  246.     }
  247.     End {
  248.         $outputAry
  249.     }
  250. }
  251.  
  252. function Get-vPCReplicaTarget {
  253. [CmdletBinding()]
  254.     param(
  255.         [Parameter(Position=0)]
  256.         [String]$Name,
  257.        
  258.         [Parameter(Position=1, ValueFromPipeline=$true)]
  259.         [PSObject[]]$InputObj
  260.     )
  261.     BEGIN {
  262.         $outputAry = @()
  263.         $dsAry = @()
  264.         if (($Name -ne $null) -and ($InputObj -eq $null)) {
  265.             $InputObj = Get-VBRJob -Name $Name
  266.         }
  267.     }
  268.     PROCESS {
  269.         foreach ($obj in $InputObj) {
  270.             if (($dsAry -contains $obj.ViReplicaTargetOptions.DatastoreName) -eq $false) {
  271.                 $esxi = $obj.GetTargetHost()
  272.                 $dtstr =  $esxi | Find-VBRDatastore -Name $obj.ViReplicaTargetOptions.DatastoreName
  273.                 $objoutput = New-Object -TypeName PSObject -Property @{
  274.                     Target = $esxi.Name
  275.                     Datastore = $obj.ViReplicaTargetOptions.DatastoreName
  276.                     StorageFree = [Math]::Round([Decimal]$dtstr.FreeSpace/1GB,2)
  277.                     StorageTotal = [Math]::Round([Decimal]$dtstr.Capacity/1GB,2)
  278.                     FreePercentage = [Math]::Round(($dtstr.FreeSpace/$dtstr.Capacity)*100)
  279.                 }
  280.                 $dsAry = $dsAry + $obj.ViReplicaTargetOptions.DatastoreName
  281.                 $outputAry = $outputAry + $objoutput
  282.             }
  283.             else {
  284.                 return
  285.             }
  286.         }
  287.     }
  288.     END {
  289.         $outputAry | Select Target, Datastore, StorageFree, StorageTotal, FreePercentage
  290.     }
  291. }
  292.  
  293. #endregion
  294.  
  295. #region Report
  296.  
  297. # HTML Stuff
  298. $headerObj = @"
  299. <html>
  300.     <head>
  301.         <title>vPowerCLI v6 Army Report</title>
  302.         <style>  
  303.             body {font-family: Tahoma; background-color:#fff;width: 800px;}
  304.             h1.top {background-color: #fb9895;color: White;font-weight: bold;font-size: 16px;vertical-align: center;padding: 5px;}
  305.             table {font-family: Tahoma;font-size: 12px;background-color: #e3e3e3;width:800px;border-collapse:collapse;}
  306.             .headerTable{background-color: #fb9895;color: White;font-weight: bold;font-size: 16px;height: 70px;vertical-align: bottom;padding: 0 0 15px 15px;border-bottom: none;}
  307.             .subheader{height: 35px;background-color: #f3f4f4;font-size: 16px;vertical-align: middle;padding: 5px 0 0 15px;color: #626365;}
  308.             table.inner tr{height: 17px;}
  309.             table.inner td{padding: 2px 3px 2px 3px;vertical-align: top;border: 1px solid #a7a9ac;}
  310.             table.inner .subheader{height: 35px;background-color: #f3f4f4;font-size: 16px;vertical-align: middle;padding: 5px 0 0 15px;color: #626365;}
  311.             th {border: 1px solid #a7a9ac;border-bottom: none;}
  312.             tr {height: 17px;}
  313.             td {background-color: #fff;border: 1px solid #a7a9ac;padding: 2px 3px 2px 3px;vertical-align: top;}  
  314.         </style>
  315.     </head>
  316. "@
  317.  
  318. if (($reportMode -eq 24) -or ($reportMode -eq 48)) {
  319.     $headSubHead = "$(Get-Date -f D) $(Get-Date -f HH:mm:ss) ($reportMode Hrs)"
  320. } else {
  321.     $headSubHead = "$(Get-Date -f D) $(Get-Date -f HH:mm:ss) ($reportMode)"
  322. }
  323.  
  324. $bodyTop = @"
  325.     <body>
  326.         <table>
  327.             <tr>
  328.                 <td style="width: 80%;border: none;" class="headerTable">vPowerCLI v6 Army Report</td>
  329.                 <td style="width: 30%;border: none;vertical-align:text-top;font-size:xx-small;text-align:right;padding: 2px 3px 2px 3px;" class="headerTable">v: $vPCARversion.Custom</td>
  330.             </tr>
  331.         </table>
  332.         <table cellspacing="0" cellpadding="0" class="inner" border="0" style="margin: 0px;">
  333.             <tr>
  334.                 <td class="subheader" style="border-top: none;border-bottom: none;">
  335.                 $headSubHead
  336.                 </td>
  337.             </tr>
  338.         </table>
  339. "@
  340.  
  341. $subHead01 = @"
  342.         <table cellspacing="0" cellpadding="0" class="inner" border="0" style="margin: 0px;">
  343.             <tr>
  344.                 <td class="subheader" style="border-top: none;border-bottom: none;">
  345. "@
  346.  
  347. $subHead02 = @"
  348.                 </td>
  349.             </tr>
  350.         </table>
  351. "@
  352.  
  353. $vbrMasterHash = @{"Coordinator" = "$((gc env:computername).ToLower())";"Total" = $totalJobCount.Count;
  354. "Successfull" = $succesJobCount.Count; "Warning" = $warningJobCount.Count; "Failed" = $failedJobCount.Count;}
  355.  
  356. $vbrMasterObj = New-Object -TypeName PSObject -Property $vbrMasterHash
  357.  
  358. $bodyMasterT =  $vbrMasterObj | Select Coordinator, @{Name="Total Jobs"; Expression = {$_.Total}},
  359. @{Name="Successfull"; Expression = {$_.Successfull}}, @{Name="Warning"; Expression = {$_.Warning}},
  360. @{Name="Failed"; Expression = {$_.Failed}} |
  361. ConvertTo-HTML -Fragment
  362.  
  363. $bodyMasterB = Get-Service -Name "*Veeam*" | Select @{Name="Service Name"; Expression = {$_.DisplayName}}, Status |
  364. ConvertTo-HTML -Fragment
  365.  
  366. $bodyMasterB = $subHead01 + "Services" + $subHead02 + $bodyMasterB
  367.  
  368. if ($jlines -eq $true) {
  369.     $counter = @($seshList | ?{($_.Result -eq "Warning") -or ($_.Result -eq "Failed")})
  370.     if ($counter.count -gt 0) {
  371.         $bodyjLines = $seshList | ?{($_.Result -eq "Warning") -or ($_.Result -eq "Failed")} | Sort Creationtime -Descending | Select @{Name="Job Name"; Expression = {$_.Name}},
  372.         @{Name="Start Date"; Expression = {$_.Progress.StartTime.ToShortDateString()}},
  373.         @{Name="Start Time"; Expression = {$_.Progress.StartTime.ToShortTimeString()}},
  374.         @{Name="Stop Time"; Expression = {$_.Progress.StopTime.ToShortTimeString()}}, @{Name="Duration"; Expression = {Get-Date "$($_.Progress.Duration)" -f HH:mm:ss}},
  375.         @{Name="Read (GB)"; Expression = {[Math]::Round([Decimal]$_.Progress.ReadSize/1GB, 2)}},
  376.         @{Name="Write (GB)"; Expression = {[Math]::Round([Decimal]$_.Progress.StoredSize/1GB, 2)}}, Result | ConvertTo-HTML -Fragment
  377.         $bodyjLines = $subHead01 + "Job Details" + $subHead02 + $bodyjLines
  378.     }
  379. }
  380.  
  381. if ($viProxyList -ne $null) {
  382.     $bodyProxy = Get-vPCProxyInfo -Sessions $seshList | Select @{Name="Proxy Host"; Expression = {$_.RealName}},
  383.     @{Name="IP Address"; Expression = {$_.IP}}, Status, @{Name="RT (ms)"; Expression = {$_.Responce}}, Disabled,
  384.     @{Name="Read (GB)"; Expression = {$_.ReadData}}, @{Name="Write (GB)"; Expression = {$_.WriteData}},
  385.     @{Name="Util (%)"; Expression = {$_.Util}} | ConvertTo-HTML -Fragment
  386.     $bodyProxy = $subHead01 + "vSphere Proxy Details" + $subHead02 + $bodyProxy
  387. }
  388.  
  389. #if ($hvProxyList -ne $null) {
  390. #}
  391.  
  392. if ($repoList -ne $null) {
  393.     $bodyRepo = $repoList | Get-vPCRepoInfo | Select @{Name="Repository Name"; Expression = {$_.Target}},
  394.     @{Name="Path"; Expression = {$_.Storepath}}, @{Name="Free (GB)"; Expression = {$_.StorageFree}},
  395.     @{Name="Total (GB)"; Expression = {$_.StorageTotal}}, @{Name="Free (%)"; Expression = {$_.FreePercentage}} |
  396.     ConvertTo-HTML -Fragment
  397.     $bodyRepo = $subHead01 + "Repository Details" + $subHead02 + $bodyRepo
  398. }
  399.  
  400. if ($repList -ne $null) {
  401.     $bodyReplica = $repList | Get-vPCReplicaTarget | Select @{Name="Replica Target"; Expression = {$_.Target}}, Datastore,
  402.     @{Name="Free (GB)"; Expression = {$_.StorageFree}}, @{Name="Total (GB)"; Expression = {$_.StorageTotal}},
  403.     @{Name="Free (%)"; Expression = {$_.FreePercentage}} | ConvertTo-HTML -Fragment
  404.     $bodyReplica = $subHead01 + "Replica Details" + $subHead02 + $bodyReplica
  405. }
  406.  
  407. $footerObj = @"
  408. </body>
  409. </html>
  410. "@
  411. $htmlOutput = $headerObj + $bodyTop + $bodyMasterT + $bodyMasterB + $bodyjLines + $bodyProxy + $bodyRepo + $bodyReplica + $footerObj
  412. #endregion
  413.  
  414. #region Output
  415. if ($sendEmail -eq 1) {
  416.     $body = $htmlOutput
  417.     $smtp = New-Object System.Net.Mail.SmtpClient $emailHost
  418.     $smtp.Credentials = New-Object System.Net.NetworkCredential($emailUser, $emailPass);
  419.     $msg = New-Object System.Net.Mail.MailMessage $emailFrom, $emailTo, $emailSubject, $body
  420.     $msg.isBodyhtml = $true
  421.     $smtp.send($msg)
  422. } else {
  423.     $htmlOutput | Out-File $file
  424.     Invoke-Expression $file
  425. }
  426. #endregion
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement