To keep control of a complex Datacenter good monitoring tools are necessary. In my opinion one of the major feature of a good monitoring solution is the capability to correlate data from different sources. VMware vRealize Operations Manager is a great solution if you run a VMware based SDDC with a mix of VMware and Partner Products. You can out of the box correlate metrics from VMware NSX, VMware vSphere, VMware VSAN and a lot of other VMware Products. But also integration of Third-Party solutions like the Blue Medora NetApp Storage Management Pack are possible. In most VMware SDDC`s also Veeam Backup & Replication is in use, so I tried to create a Veeam Integration with vRealize Operations Manager. I need to mention that Veeam offers with Veeam ONE also their own monitoring solution with a deep VMware vSphere and Veeam Integration. But in complex datacenter designs with a wide range of products that need to be integrated VMware vRealize Operations Manager is more flexible at this point.
My concept of a Veeam Integration with vRealize Operations Manager is only a proof of concept at this point. And even if it works is it not ready for production yet!
Veeam Protection View
The main goal of the proof of concept was to create a view that shows the Veeam protection state of the virtual machines. The gathered data is identical to the data I have collected with an earlier PowerShell project - Veeam vSphere Interactions with PowerShell.
The View has only my custom properties as Data with shorter Metric Labels.
Group of Veeam Protected VMs
With the additional properties regarding the Veeam protection status I am also able to create new groups. The groups can be used to apply other Policies or to limit the permissions of users.
vRealize Operations Manager API
An easy possibility to add additional properties to resources (in my case virtual machine) in VMware vRealize Operations Manager is the API. vMan.ch wrote a great Blog Post how to add properties with the Suite-API. My Veeam Integration with vRealize Operations Manager is essentially a PowerShell Script that pushes collected data to the vRealize Operations Manager API.
The documentation of the Suite-API can accessed on every vRealize Operations Manager Appliance: https:///suite-api/
This is the sample request how to add custom properties with XML as payload:
Name |
Description |
Type |
Required |
statKey |
Stat Key for which the data is being posted |
xs:string |
yes |
timestamps |
The array of timestamps at which the data is being posted |
xs:long |
yes |
data |
The numeric data that is being posted (optional) |
xs:double |
no |
values |
The string values that are being posted (optional) |
xs:string |
no |
My real live example of a XML Body:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ops:property-contents xmlns:ops="http://webservice.vmware.com/vRealizeOpsMgr/1.0/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ops:property-content statKey="VEEAM|LastRestorePoint">
<ops:timestamps>1518771941000</ops:timestamps>
<ops:values>2/15/2018 2:49:59 PM</ops:values>
</ops:property-content>
<ops:property-content statKey="VEEAM|LastBackupJob">
<ops:timestamps>1518771941000</ops:timestamps>
<ops:values>vRops-Test</ops:values>
</ops:property-content>
<ops:property-content statKey="VEEAM|FirstRestorePoint">
<ops:timestamps>1518771941000</ops:timestamps>
<ops:values>2/14/2018 3:43:34 PM</ops:values>
</ops:property-content>
<ops:property-content statKey="VEEAM|IsProtected">
<ops:timestamps>1518771941000</ops:timestamps>
<ops:values>True</ops:values>
</ops:property-content>
<ops:property-content statKey="VEEAM|VmRestorePoints">
<ops:timestamps>1518771941000</ops:timestamps>
<ops:data>2</ops:data>
</ops:property-content>
<ops:property-content statKey="VEEAM|BackupServer">
<ops:timestamps>1518771941000</ops:timestamps>
<ops:values>VBR01</ops:values>
</ops:property-content>
</ops:property-contents>
|
You can also use your Browser or even better, Tools like Postman the leverage the Suite-API:
Veeam Integration with vRealize Operations Manager PowerShell Script
My PowerShell script uses a modification of an older Veeam Project to get the protection details about the vSphere virtual machines from Veeam, I have only added some additional output to the function (Get-VeeamProtectionEnhanced). This data can now be used to create the API Request.
In difference to the API-Only solution from vMan.ch I have used the PowerCLI Cmdlet Get-OMResource to find the correct resource to add the properties.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
# Credits: http://vman.ch/vrops-suite-api-properties-import/
#region: SSL Config for SelfSigned Cert and force TLS 1.2
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
[System.Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
#endregion
#region: Functions
function Get-VeeamProtectionEnhanced {
<#
.NOTES
Forked From:
https://github.com/mycloudrevolution/Veeam-vSphere-Interactions/blob/master/Veeam.PowerCLI-Interactions/functions/Get-VeeamProtection.psm1
#>
#Requires -Version 4
#Requires -Modules VMware.VimAutomation.Core, @{ModuleName="VMware.VimAutomation.Core";ModuleVersion="6.3.0.0"}
#Requires -PSSnapin VeeamPssnapin
[CmdletBinding()]
param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true, Position=0)]
[ValidateNotNullorEmpty()]
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]]
$myVMs
)
Begin {
if ($global:DefaultVIServer) {
Write-Verbose "VI Server Connected"
if ($ViServer = Get-VBRServer -Name $global:DefaultVIServer.Name) {
Write-Verbose "VI Server '$($ViServer.Name)' in Veeam Inventory found"
}
else {
throw "VI Server not in Veeam found!"
}
}
else {
throw "no VI Server Connected!"
}
$VbrReastorePoints = Get-VBRRestorePoint
$VBRServerObject = Get-VBRServer | Where-Object {$_.Description -eq "Backup server" -and $_.Type -eq "Local"}
}
Process {
$MyView = @()
foreach ($MyVm in $MyVms) {
[DateTime] $NowDate = (Get-date)
[int64] $NowDateEpoc = Get-Date -Date $NowDate.ToUniversalTime() -UFormat %s
$NowDateEpoc = $NowDateEpoc*1000
$MoRef = $MyVm.ExtensionData.MoRef.Value
if ($VeeamVm = Find-VBRViEntity -Server $ViServer | Where-Object {$_.Reference -eq $MoRef}) {
[Array]$VmRestorePoints = $VbrReastorePoints | Where-Object {$_.InsideDir.Split("(,)") -eq $MoRef}
if ($VmRestorePoints.count -gt 0) {$IsProtected = $true} else {$IsProtected = $false}
$LastRestorePoint = $VmRestorePoints | Sort-Object CreationTime | Select-Object -Last 1
$LastBackupJob = Get-VBRBackup | Where-Object {$_.Id -eq $LastRestorePoint.BackupId}
$FirstRestorePoint = $VmRestorePoints | Sort-Object CreationTime | Select-Object -First 1
$Report = [PSCustomObject] @{
VmName = $VeeamVm.name
MoRef = $MoRef
IsProtected = $IsProtected
VmRestorePoints = $VmRestorePoints.count
LastRestorePoint = $LastRestorePoint.CreationTime
LastBackupJob = $LastBackupJob.Name
FirstRestorePoint = $FirstRestorePoint.CreationTime
BackupServer = $VBRServerObject.Name
VmObject = $MyVm
Date = $NowDate
DateEpoch = $NowDateEpoc
}
$MyView += $Report
}
}
$MyView
}
}
#endregion
#region: Pre-Requirments
Import-Module VMware.VimAutomation.Core, VMware.VimAutomation.vROps
Add-PSSnapin VeeamPssnapin
$WarningPreference = "SilentlyContinue"
#endregion
#region: Global definitions
$vRopsFQDN = "<vRopsFQDN>"
$vCenterFQDN = "<vCenterFQDN>"
$VeeamFQDN = "<VeeamFQDN>"
$vRopsCred = Import-Clixml -Path "C:\Secure\vRops-Credential.xml"
$vCenterCred = Import-Clixml -Path "C:\Secure\vCenter-Credential.xml"
$VeeamCred = Import-Clixml -Path "C:\Secure\Veeam-Credential.xml"
$vCenterDcFilter = "Production"
#endregion
#region: Connections
Connect-VIServer -Server $vCenterFQDN -Credential $vCenterCred
Connect-OMServer -Server $vRopsFQDN -Credential $vRopsCred
Connect-VBRServer -Server $VeeamFQDN -Credential $VeeamCred
#endregion
#region: Get Protected VMs
$ProtectedVms = Get-Datacenter -Name $vCenterDcFilter | Get-VM | Get-VeeamProtectionEnhanced
if (!$ProtectedVms) {
Throw "No Veeam Protected VMs found"
}
#endregion
#region: Create XML Structure and populate variables from the Metadata file
foreach ($ProtectedVm in $ProtectedVms) {
$XmlFile = @('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ops:property-contents xmlns:ops="http://webservice.vmware.com/vRealizeOpsMgr/1.0/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ops:property-content statKey="VEEAM|LastRestorePoint">
<ops:timestamps>{0}</ops:timestamps>
<ops:values>{1}</ops:values>
</ops:property-content>
<ops:property-content statKey="VEEAM|LastBackupJob">
<ops:timestamps>{0}</ops:timestamps>
<ops:values>{2}</ops:values>
</ops:property-content>
<ops:property-content statKey="VEEAM|FirstRestorePoint">
<ops:timestamps>{0}</ops:timestamps>
<ops:values>{3}</ops:values>
</ops:property-content>
<ops:property-content statKey="VEEAM|IsProtected">
<ops:timestamps>{0}</ops:timestamps>
<ops:values>{4}</ops:values>
</ops:property-content>
<ops:property-content statKey="VEEAM|VmRestorePoints">
<ops:timestamps>{0}</ops:timestamps>
<ops:data>{5}</ops:data>
</ops:property-content>
<ops:property-content statKey="VEEAM|BackupServer">
<ops:timestamps>{0}</ops:timestamps>
<ops:values>{6}</ops:values>
</ops:property-content>
</ops:property-contents>' -f $ProtectedVm.DateEpoch,
$ProtectedVm.LastRestorePoint,
$ProtectedVm.LastBackupJob,
$ProtectedVm.FirstRestorePoint,
$ProtectedVm.IsProtected,
$ProtectedVm.VmRestorePoints,
$ProtectedVm.BackupServer
)
[xml]$XmlSend = $XmlFile
$OmRessource = Get-OMResource -Entity $ProtectedVm.VmObject
if ($OmRessource) {
$UrlSend = 'https://' + $vRopsFQDN + '/suite-api/api/resources/'+ $OmRessource.Id + '/properties'
$ContentType = "application/xml;charset=utf-8"
Invoke-RestMethod -Method POST -uri $UrlSend -Body $XmlSend -Credential $vRopsCred -ContentType $ContentType -Verbose
}
else {
Throw "No vRealize Operations Manager Ressource for '$($ProtectedVm.VmName)' Found"
}
}
#endregion
#region: Disconnect
Disconnect-VIServer -Server * -Force:$true -Confirm:$false
Disconnect-OMServer -Server * -Force:$true -Confirm:$false
Disconnect-VBRServer
#endregion
|
Script Details:
- 4 - 16 : Accept Self Signed Certificates and force TLS 1.2
- 20 - 89 : Function Get-VeeamProtectionEnhanced
- 39 - 50 : Make sure vCenter is connected and with the same name available in Veeam
- 58 - 67 : Collect per VM details
- 69 - 82 : Build return
- 93 - 94 : Load Modules and SnapIns
- 99 - 105 : Load global definitions and saved credential (See also: Import-Clixml and Export-Clixml)
- 109 - 111 : Connect vCenter, Veeam and Operations Manager
- 115 - 118 : Get vSphere VMs and their protection details
- 123 - 156 : Build XML for the API Post
- 160 : Get Operations Manager Ressource from vSphere VM
- 162 - 169 : Invoke API Post
- 175 - 177 : Disconnect vCenter, Veeam and Operations Manager
Known Problems
As I started playing with the custom properties I was wondering why the new properties were not available as a filter option in Views or Groups. But John Dias was able to clarify the situation (Many thanks!):
That means it can take while until the new properties pop up in all Filters. The more objects have this properties the faster it will work.