Active IQ Unified Manager Discussions
Active IQ Unified Manager Discussions
Has anyone had any luck in passing environment variables from OCUM 6.3 to a script? Long story short, I am working with BPPM Msend.exe to create incident tickets when we have alerts. In DFM 5.2 I was able to pass the DFM_EVENT_SEVERITY, DFM_SOURCE_TYPE, and so forth to the script. This allowed me to set the priority of incident tickets and also customize the alert messages. In 6.3, I found a very short piece of information, but it has very limited items passed and does not state if they are always passed with the same ARGV[x] number.
This is what I have found so far.
Arguments
-eventID
-eventSourceID
-eventSourceName
-eventSourceType
-eventState-eventArgs
Example for obtaining arguments from scripts
print "$ARGV[0] : $ARGV[1]\n"
print "$ARGV[2] : $ARGV[3]\n"
When an alert is generated, this script is executed and the following output is displayed:
-eventID : 290
-eventSourceID : 4138
Unfortunately, this is not telling me (or anyone else) much of anything. I have communications in with the OCUM developers, but not sure how long that will take. As of right now, we have 8.3.1 Systems that are not being alerted on when we have issues.
My current 5.2 script is in powershell, and although I do not like powershell, I would like to keep the 6.3 script in the same.
Any help or sample scripts would be greatly appreciated!!
Solved! See The Solution
Hi,
I've a had a closer look and totally agree with you that this is very poorly implemented and documented in OCUM 6.X compared with environment variable flexibilty and simplicity available in DFM 5.X. EG:
https://kb.netapp.com/support/index?page=content&id=3012180
Note: I tried using environment variables in this method for OCUM6.X but it's not implemented (Adding to my list for engineering developement requests).
From a powershell perspective the "-eventID" parameter value is $args[1]. EG the parameter name "eventID" = $args[0] and the parameter value is $args[1] (eventID = X)
So with this in mind i had a look at what you might be able to do if you get the script which is attached to your alarm to invoke a MySQL using the EventID as basis. Something like...
SELECT event.id AS 'event_id', event.eventTimeStamp AS 'event_time_stamp', event.impactArea AS 'event_impact', event.source_type, event.source_fullName AS 'source_full_name', eventtypevalue.internalName AS 'internal_name', vserverlivelistdtoview.clusterName AS 'cluster_name', vserverlivelistdtoview.name AS 'vserver_name' FROM ocum.event, ocum.eventtypevalue, ocum.vserverlivelistdtoview WHERE event.id = 20006 AND vserverlivelistdtoview.clusterId = event.cluster_id AND vserverlivelistdtoview.id = event.vserver_id AND eventtypevalue.id = event.value_id
(where event.id = 20006 in the powershell code would be "event.id = $eventID" or "event.id = $args[1]")
With a some modification this will probably return the type of detail are looking for. The above SQL query was for a test i put together for an alert setting a volume state to offline. EG:
event_id,event_time_stamp,event_impact,source_type,source_full_name,internal_name,cluster_name,vserver_name 20006,2016-03-03 17:03:29,AVAILABILITY,inventory.ontap.storage.FlexVol,vserver1/volume_001,offline,cluster1,vserver1
Hope that gives you some ideas. When i get some time i'll post a more comprehsive example in powershell.
/matt
Hi,
Check the "event-iter" API in the NMSDK 5.4 for ocum. You need to load the "ManageOntap.dll" and create a connection to the OCUM server. Here is a code snippet to list the events:
#'------------------------------------------------------------------------------ Try{ $naElement = New-Object NetApp.Manage.naElement("event-iter") [Xml]$output = $naServer.InvokeElem($naElement) }Catch{ Write-Warning -Message $("Failed enumerating OnCommand Unified Manager Events on ""$HostName"". Error " + $_.Exception.Message) Exit } Write-Host $("There are " + $output.results.'num-records' + " events") $events = $output.results.'records'.'event-info' ForEach($event In $events){ $event.'event-info'.'event-id' } #'------------------------------------------------------------------------------
Here is an example of the properties values that can be enumerated about each event.
event-about : Aggregate Renamed event-arguments : event-arguments event-category : Others event-condition : Aggregate aggr0 is renamed to testc1n1_aggr0. event-id : 20 event-impact-area : configuration event-impact-level : event event-name : Aggregate Renamed event-severity : information event-source-name : testc1n1:testc1n1_aggr0 event-source-resource-key : 4da6250c-8d16-11e5-94f9-005056ac2b80:type=aggregate,uuid=809a94ec-3747-48a8-9b54-12a8c741b482 event-source-type : aggregate event-state : NEW event-time : 1447758913 event-type : aggregate.renamed
Given you know the event ID it's possible to enumerate all property values for that event. Is this the type of detail you are looking for? Let me know i can send you my code.
/matt
Hi,
I've a had a closer look and totally agree with you that this is very poorly implemented and documented in OCUM 6.X compared with environment variable flexibilty and simplicity available in DFM 5.X. EG:
https://kb.netapp.com/support/index?page=content&id=3012180
Note: I tried using environment variables in this method for OCUM6.X but it's not implemented (Adding to my list for engineering developement requests).
From a powershell perspective the "-eventID" parameter value is $args[1]. EG the parameter name "eventID" = $args[0] and the parameter value is $args[1] (eventID = X)
So with this in mind i had a look at what you might be able to do if you get the script which is attached to your alarm to invoke a MySQL using the EventID as basis. Something like...
SELECT event.id AS 'event_id', event.eventTimeStamp AS 'event_time_stamp', event.impactArea AS 'event_impact', event.source_type, event.source_fullName AS 'source_full_name', eventtypevalue.internalName AS 'internal_name', vserverlivelistdtoview.clusterName AS 'cluster_name', vserverlivelistdtoview.name AS 'vserver_name' FROM ocum.event, ocum.eventtypevalue, ocum.vserverlivelistdtoview WHERE event.id = 20006 AND vserverlivelistdtoview.clusterId = event.cluster_id AND vserverlivelistdtoview.id = event.vserver_id AND eventtypevalue.id = event.value_id
(where event.id = 20006 in the powershell code would be "event.id = $eventID" or "event.id = $args[1]")
With a some modification this will probably return the type of detail are looking for. The above SQL query was for a test i put together for an alert setting a volume state to offline. EG:
event_id,event_time_stamp,event_impact,source_type,source_full_name,internal_name,cluster_name,vserver_name 20006,2016-03-03 17:03:29,AVAILABILITY,inventory.ontap.storage.FlexVol,vserver1/volume_001,offline,cluster1,vserver1
Hope that gives you some ideas. When i get some time i'll post a more comprehsive example in powershell.
/matt
Matt,
Thanks for the info and details example. This will definately help me out some. Although it may take a bit more time to re-write the script, I think it is a viable solution at least for the time being.
Hi,
This information is great, however they seem to have changed the MYSQL table layout in OCUM 6.4. Have you had time to look at OCUM 6.4? have any updated MYSQL queries which would do the same as above for example?
Thanks!
I am currently looking for the same information. I need to update our scripts as well, but have not had time to find out what the new layout is.
it looks like it is $args that is the variable that is passed out
What I am actually trying to do is replicate the pre canned email alert from OCUM but from PowerShell/MYSQL:
Risk - Cluster Lacks Spare Disks
Impact Area - Availability
Severity - Warning
State - New
Source - xxxxxx
Trigger Condition - The cluster lacks spare disks on nodes -xxxxxxx.
PowerShell can then send it via REST to our incident tracking system.
Any ideas?
Hi,
Yes it is possible to enumerate the event information (by ID) in OCUM using the SDK. The database schema between OCUM6.3\6.4 has changed so you would need to modify the query. I'd recommend invoking a ZAPI call rather than a SQL query to enumerate the event information as the schema might change in future. To do this you will need to download the SDK as the "ManageOntap.dll" file is required. This file is located in the "netapp-manageability-sdk-5.6\lib\DotNet" folder when you extract the download.
Note that if you are using WFA you can also copy the file from the "\PoSH\Modules\WFAWrapper" folder in your WFA installation directory (default "C:\Program Files\NetApp\WFA\PoSH\Modules\WFAWrapper"). Although I'd recommend using the latest "ManageOntap.dll" file from the NMSDK though to ensure the ZAPI's work with OCUM6.4\7.0. You can download the NMSDK here:
http://mysupport.netapp.com/NOW/download/software/nmsdk/5.6/
Here is some "example" source code that enumerates OCUM event information by Event ID. If you are attaching a script to an alarm then the Event ID is $args[1].
Example Event (OCUM GUI)
Example Output:
PS C:\Scripts\PowerShell\Projects\OCUM> .\ocum.ps1 -EventId 7 Loaded file "C:\Scripts\PowerShell\Projects\OCUM\ManageOntap.dll" Invoking API "dfm-about" to check connectivity to "TESTOC64" using the "HTTPS" protocol Event About: Availability of spare disks for aggregates in a cluster Event Category: Cluster with Low Spare Disks Event Condition: The cluster lacks spare disks on nodes - testc2n1. Event Impact Area: availability Event Impact Area: risk Event Name: Cluster Lacks Spare Disks Event Type: cluster.spares Event Source Type: cluster Event Source Name: cluster2 Event Source Resource Key: b3e53f0a-dc85-11e6-acfc-005056ac4ac8:type=cluster,uuid=b3e53f0a-dc85-11e6-acfc-005056ac4ac8 Event State: NEW Event Time: 01/18/2017 11:09:28
Note: You need to save the "ManageOntap.dll" file in the same folder as the script. EG:
C:\Scripts\PowerShell\Projects\OCUM>dir /b ManageOntap.dll ocum.ps1
It the code below you will be securely prompted for credentials for the admin OCUM user. If you want to automate the process you will need to cache\encrypt administrative credentials on your OCUM server (IE to a file or registry key)
Source Code:
Param( [Parameter(Mandatory = $True, HelpMessage = "The OCUM Event ID to enumerate")] [Int]$EventId ) #'------------------------------------------------------------------------------ Function ConvertFrom-UnixTimestamp{ [CmdletBinding()] Param( [Parameter(Position=0, Mandatory=$True, ValueFromPipeLine=$True, ValueFromPipeLineByPropertyName=$True)] [String]$Timestamp ) [TimeZone]::CurrentTimeZone.ToLocalTime(([DateTime]'1/1/1970').AddSeconds($Timestamp)) }#End Function #'------------------------------------------------------------------------------ Function New-ZapiServer{ <# .SYNOPSIS Cmdlet to create a new ZAPI server object. .DESCRIPTION The cmdlet creates a ZAPI object from which Data ONTAP or Unified Manager ZAPIs can be called. .PARAMETER Host The server hostname or IP address .PARAMETER Port The port number to connet to. For HTTPS, use 443 .PARAMETER Type The connecting server type. Valid values are FILER for Data ONTAP and DFM for a Unified Manager server. .PARAMETER VFiler The vFiler unit name in the Filer. Used with the type "FILER" for running ZAPIs on the specified vFiler unit. .EXAMPLE New-ZapiServer -Host $DFMServerName -Type DFM -Credentials $credentials #> Param( [Parameter(Mandatory = $True)] [String]$HostName, [Parameter(Mandatory = $False)] [Int]$PortNumber, [Parameter(Mandatory = $True)] [ValidateSet("FILER", "DFM")] [String]$ZapiType, [Parameter(Mandatory = $True)] [System.Management.Automation.PSCredential]$Credentials, [Parameter(Mandatory = $False)] [String]$VFiler ) #'--------------------------------------------------------------------------- #'Create the NaServer server object based on the ZAPI type. #'--------------------------------------------------------------------------- If($ZapiType -eq "DFM"){ [NetApp.Manage.NaServer]$zapiServer = New-Object NetApp.Manage.NaServer($HostName, "1", "0") }Else{ [NetApp.Manage.NaServer]$zapiServer = New-Object NetApp.Manage.NaServer($HostName, "1", "14") If($VFiler -And $VFiler.Length -gt 0){ $zapiServer.SetVfilerTunneling($VFiler) } } #'--------------------------------------------------------------------------- #'Enumerate the username and password from the credential object. #'--------------------------------------------------------------------------- [String]$domain = $credentials.GetNetworkCredential().domain [String]$user = $credentials.GetNetworkCredential().username [String]$password = $credentials.GetNetworkCredential().password If($domain -ne "" -Or $domain -ne $Null){ If($domain.Contains(".")){ [String]$userName = "$user`@$domain" }Else{ If($credentials.UserName.Contains("\") -And $credentials.UserName.SubString(0, 1) -ne "\"){ [String]$userName = $credentials.UserName }Else{ [String]$userName = $user } } } #'--------------------------------------------------------------------------- #'Set the username and password for the NaServer object. #'--------------------------------------------------------------------------- $zapiServer.SetAdminUser($userName, $password) $zapiServer.ServerType = $ZapiType If($PortNumber){ $zapiServer.port = $PortNumber } #'--------------------------------------------------------------------------- #'Check connectivity using HTTPS #'--------------------------------------------------------------------------- $zapiServer.TransportType = 'HTTPS' $result = Check-ZapiConnection -ZapiServer $zapiServer -ZapiType $ZapiType -HostName $HostName -ProtocolName "HTTPS" If($result -eq -1){ Write-Host "Failed connecting to ""$HostName"" using the ""HTTPS"" protocol" #'------------------------------------------------------------------------ #'Check connectivity using HTTP #'------------------------------------------------------------------------ $zapiServer.TransportType = 'HTTP' $result = Check-ZapiConnection -ZapiServer $zapiServer -ZapiType $ZapiType -HostName $HostName -ProtocolName "HTTP" If($result -eq -1){ Write-Warning -Message $("Failed connecting to ""$HostName"" using the ""HTTP"" protocol") Return -1; } } Return $zapiServer; }#End Function #'------------------------------------------------------------------------------ Function Check-ZapiConnection{ Param( [Parameter(Mandatory = $True)] [NetApp.Manage.NaServer]$ZapiServer, [Parameter(Mandatory = $True)] [ValidateSet("FILER", "DFM")] [String]$ZapiType, [Parameter(Mandatory = $True)] [String]$HostName, [Parameter(Mandatory = $True)] [String]$ProtocolName ) #'--------------------------------------------------------------------------- #'invoke the API based on the ZAPI type. #'--------------------------------------------------------------------------- If($ZapiType -eq "DFM"){ Try{ [String]$apiName = "dfm-about" Write-Host "Invoking API ""$apiName"" to check connectivity to ""$HostName"" using the ""$ProtocolName"" protocol" $output = $ZapiServer.Invoke($apiName) }Catch{ Return -1 } }Else{ Try{ [String]$apiName = "system-get-version" Write-Host "Invoking API ""$apiName"" to check connectivity to ""$HostName"" using the ""$ProtocolName"" protocol" $output = $ZapiServer.Invoke($apiName) }Catch{ Return -1 } } Return 0; }#End Function #'------------------------------------------------------------------------------ #'Initialization Section. Define Global Variables. #'------------------------------------------------------------------------------ [String]$scriptPath = Split-Path($MyInvocation.MyCommand.Path) [String]$scriptSpec = $MyInvocation.MyCommand.Definition [String]$scriptBaseName = (Get-Item $scriptSpec).BaseName [String]$scriptName = (Get-Item $scriptSpec).Name [String]$fileSpec = "$scriptPath\ManageOntap.dll" [String]$zapiType = "DFM" [Int]$zapiPortNumber = 443 [String]$hostname = $env:computername #'------------------------------------------------------------------------------ #'Load the "ManageONTAP.dll" file #'------------------------------------------------------------------------------ Try{ [Reflection.Assembly]::LoadFile($fileSpec) | Out-Null Write-Host "Loaded file ""$fileSpec""" }Catch{ Write-Warning -Message $("Failed loading file ""$fileSpec"". Error " + $_.Exception.Message) Break;; } #'------------------------------------------------------------------------------ #'Prompt for OCUM credentials. #'------------------------------------------------------------------------------ [System.Management.Automation.PSCredential]$ocumCredentials = Get-Credential -Credential admin #'------------------------------------------------------------------------------ #'Create a ZAPI connection to the DFM server. #'------------------------------------------------------------------------------ $naServer = New-ZapiServer -HostName $hostName -PortNumber $zapiPortNumber -ZapiType $zapiType -Credentials $ocumCredentials #'------------------------------------------------------------------------------ If($naServer -eq -1){ Write-Warning -Message "Failed creating ZAPI connection to ""$HostName""" Break; } #'------------------------------------------------------------------------------ #'Invoke the ZAPI. #'------------------------------------------------------------------------------ Try{ $naElement = New-Object NetApp.Manage.naElement("event-iter") $naElement.AddNewChild("event-id", $eventID) $naElement.AddNewChild("max-records", "1"); [Xml]$output = $naServer.InvokeElem($naElement) }Catch{ Write-Warning -Message $("Failed invoking ZAPI on ""$HostName"". Error " + $_.Exception.Message) Break; } #'------------------------------------------------------------------------------ #'Set variables from ZAPI results. #'------------------------------------------------------------------------------ $events = $output.results.'records'.'event-info' ForEach($event In $events){ [String]$eventAbout = $event.'event-about' [String]$eventCategory = $event.'event-category' [String]$eventCondition = $event.'event-condition' [String]$eventImpactArea = $event.'event-impact-area' [String]$eventImpactLevel = $event.'event-impact-level' [String]$eventName = $event.'event-name' [String]$eventType = $event.'event-type' [String]$eventSeverity = $event.'event-severity' [String]$eventSourceType = $event.'event-source-type' [String]$eventSourceName = $event.'event-source-name' [String]$eventSourceResourceKey = $event.'event-source-resource-key' [String]$eventState = $event.'event-state' [String]$eventTime = ConvertFrom-UnixTimestamp -TimeStamp $($event.'event-time') } #'------------------------------------------------------------------------------ #'Display the event information. #'------------------------------------------------------------------------------ Write-Host "Event About: $eventAbout" Write-Host "Event Category: $eventCategory" Write-Host "Event Condition: $eventCondition" Write-Host "Event Impact Area: $eventImpactArea" Write-Host "Event Impact Area: $eventImpactLevel" Write-Host "Event Name: $eventName" Write-Host "Event Type: $eventType" Write-Host "Event Source Type: $eventSourceType" Write-Host "Event Source Name: $eventSourceName" Write-Host "Event Source Resource Key: $eventSourceResourceKey" Write-Host "Event State: $eventState" Write-Host "Event Time: $eventTime" #'------------------------------------------------------------------------------
Hope that helps
/Matt
Hi
This script is excellent, but I cannot seem to find a way to integrate it into OCUM 7.1 as you have to upload the script within the 'Manage Scripts' and then select the script within the alarm.
Regards
I have got the script to execute, but am having trouble passing the email address configured for the alert to the script. Currently I get the default OCUM script sent to me as well as the custom script which has my email address hardcoded into the script.
Any ideas?
Hi Uber,
You could try invoking a SQL query in your script to enumerate the email address matching the Script name. EG:
SELECT alert_emailaddressrecipients.emailAddress AS 'email_address' FROM ocum.alert, ocum.alert_emailaddressrecipients, ocum.script WHERE alert_emailaddressrecipients.alert_id = alert.id AND alert.scriptId = script.id AND script.name = '$scriptName'
You can dynamically determine what the script name that is running is within your OCUM script plugin directory using powershell scirpt. EG:
#'------------------------------------------------------------------------------ #'Initialization Section. Define Global Variables. #'------------------------------------------------------------------------------ [String]$scriptPath = Split-Path($MyInvocation.MyCommand.Path) [String]$scriptSpec = $MyInvocation.MyCommand.Definition [String]$scriptBaseName = (Get-Item $scriptSpec).BaseName [String]$scriptName = (Get-Item $scriptSpec).Name #'------------------------------------------------------------------------------ #'Display variables. #'------------------------------------------------------------------------------ Write-Host "Script Path`: $scriptPath" Write-Host "Script Spec`: $scriptSpec" Write-Host "Script Base Name`: $scriptBaseName" Write-Host "Script Name`: $scriptName" #'------------------------------------------------------------------------------
Example output:
PS C:\Program Files\NetApp\ocum\scriptPlugin> .\test.ps1 Script Path: C:\Program Files\NetApp\ocum\scriptPlugin Script Spec: C:\Program Files\NetApp\ocum\scriptPlugin\test.ps1 Script Base Name: test Script Name: test.ps1
This way you wouldn't have to hard code email addresses in your script if you have already configured email address in OCUM.
/Matt
I have this mostly working for version 7.1 but have run into a snag. When I run the script outside of Unified Manager it picks up all the event information just fine and will pass it to msend and create a ticket in our remedy system.
However when the script runs automatically based on a triggered event it doesn't look like the script is ever actually running as no ticket gets created. Any thoughts?
Is the event ID no longer $args[1]?
Thanks.
Hi Taber,
The $args[1] variable is definately the EventID however there does appear to be a discrepancy in the documentation.
I'm not sure if it's an error in the documentation or the variable order has changed between OCUM 6.X and 7.X
https://library.netapp.com/ecm/ecm_download_file/ECMLP2553757 (Page 81-82).
In the documented example:
$args[3] = EventSourceID
(That is incorrect, in OCUM 7.1 the "EventSourceID" is $args[8]). If
If you are ever in any doubt as to what the argument parameter names and values are...
I recommend logging them in your OCUM alarm script using the following powershell code:
$fileSpec = "C:\Program Files\NetApp\ocum\scriptPlugin\output.log"
$("OCUM Event Argument 0`: " + $args[0]) | Out-File -FilePath $fileSpec -encoding ASCII -Append
$("OCUM Event Argument 1`: " + $args[1]) | Out-File -FilePath $fileSpec -encoding ASCII -Append
$("OCUM Event Argument 2`: " + $args[2]) | Out-File -FilePath $fileSpec -encoding ASCII -Append
$("OCUM Event Argument 3`: " + $args[3]) | Out-File -FilePath $fileSpec -encoding ASCII -Append
$("OCUM Event Argument 4`: " + $args[4]) | Out-File -FilePath $fileSpec -encoding ASCII -Append
$("OCUM Event Argument 5`: " + $args[5]) | Out-File -FilePath $fileSpec -encoding ASCII -Append
$("OCUM Event Argument 6`: " + $args[6]) | Out-File -FilePath $fileSpec -encoding ASCII -Append
$("OCUM Event Argument 7`: " + $args[7]) | Out-File -FilePath $fileSpec -encoding ASCII -Append
$("OCUM Event Argument 8`: " + $args[8]) | Out-File -FilePath $fileSpec -encoding ASCII -Append
$("OCUM Event Argument 9`: " + $args[9]) | Out-File -FilePath $fileSpec -encoding ASCII -Append
$("OCUM Event Argument 10`: " + $args[10]) | Out-File -FilePath $fileSpec -encoding ASCII -Append
$("OCUM Event Argument 11`: " + $args[11]) | Out-File -FilePath $fileSpec -encoding ASCII -Append
Example output:
OCUM Event Argument 0: -eventID
OCUM Event Argument 1: 54
OCUM Event Argument 2: -eventName
OCUM Event Argument 3: LUN
OCUM Event Argument 4: Offline
OCUM Event Argument 5: -eventSeverity
OCUM Event Argument 6: critical
OCUM Event Argument 7: -eventSourceID
OCUM Event Argument 8: 224
OCUM Event Argument 9: -eventSourceName
OCUM Event Argument 10: vserver4:/volume_002/lun_001
OCUM Event Argument 11: -eventSourceType
OCUM Event Argument 12: LUN
/Matt