Pulling OpsMgr Company Knowledge from Management Pack and send it to email

Pulling OpsMgr Company Knowledge from Management Pack and send it to email

  • Comments 2
  • Likes

Some weeks ago I got a question from Marnix Wolf asking if it’s possible to retrieve Company Knowledge for a monitor or rule and sent that as email. And after an evening playing around with PowerShell I created a PowerShell script that could do exactly that.

 

Pre-requisites:

  • OpsMgr 2007 (R2)
  • PowerShell version 2.0 (I only tested the script in PowerShell version 2.0)
  • Company Knowledge stored in one Management Pack

 

Background info:

I hope you know you can add your own Company Knowledge for a rule or monitor.  Administrators can add their own knowledge to rules and monitors to expand the troubleshooting information and provide company-specific information for operators, which is known as company knowledge. Administrators can use company knowledge to document any overrides implemented for a monitor or rule, along with the explanation for the customization and any other information that might be useful.

Operations Manager stores company knowledge in a management pack. Sealed management packs cannot be modified, so Operations Manager saves customizations such as company knowledge in a custom management pack. By default, Operations Manager saves all customizations to the Default Management Pack. As a best practice, you should instead create a separate management pack for each sealed management pack you want to customize. More info about adding Company Knowledge can be found here. For the pre-requisites you can take a look at this blogpost on the MOMTeam blogsite.

 

Steps:

  1. Let’s first create a Management Pack to store the Company Knowledge.
    image

    I’ve created a Management Pack called Stefan – Company Knowledge Test MP.
  2. The next steps is to create Company Knowledge for some monitors and rules.
  1. Open in the OpsMgr Console a Monitor for which we want to add Company Knowledge. I choose the AD Domain Availability Health Rollup Monitor because there is an Alert for this monitor in my demo environment.
    image
  2. Open the Company Knowledge Tab and select Edit.
    image
  3. Word will be launched (in my case it’s Word 2010) and insert the Company Knowledge you want to Edit.
    image
  4. Once this is done, click File/Save. Do NOT close out the Word document. If you do you will lose any information that you had saved.
  5. image 
  6. Press the Save button  to save Company Knowledge and make sure you save it in the correct Management Pack!
  7. Let’s do the same for a rule. I selected the AD Agent Assignment: Rule Failure rule.
  8. Follow steps 1 to 7 again to add your Company Knowledge for this rule.
    image
  9. And again save the Company Knowledge in the same Management Pack.

 

Now we saved the Company Knowledge for the monitor and rule we can extract this info from the Management Pack. It’s also somewhere in the database but extracting it from the Management Pack is the easiest way IMO.

 

These are the high-level steps that need to be executed in the PowerShell script:

  1. Find Monitor or Rule for Alert.
  2. Export Management where Company Knowledge is saved.
  3. Parse Company Knowledge for Monitor from exported XML MP.
  4. Email Company Knowledge

 

Step 1. Find Monitor or Rule for Alert.

#Error Handling
#This is because when there is no monitor found in the FindMonitorForAlert Function
#the script needs to continue.
$ErrorActionPreference="SilentlyContinue"
$Error.psbase.clear()

       
Function Initialize
{
     ## Check for OpsMgr shell
    if ((Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.EnterpriseManagement.OperationsManager.Client'}) -eq $null)
    {
        Write-Host "Load OpsMgr Snapin if not loaded" -foregroundcolor red
        LoadSnapin("localhost")
    }
}
     
Function LoadSnapin($RMS)
{
    add-pssnapin "Microsoft.EnterpriseManagement.OperationsManager.Client";
    set-location "OperationsManagerMonitoring::";
    new-managementGroupConnection -ConnectionString:$RMS;
    set-location $RMS;
}
     
     
Function FindMonitorOrRuleForAlert($AlertName)
{
    #Find an alert with resolution state new
    $alert = get-alert | where {$_.Name -eq "$AlertName"}
   
    #Check if Alert is available
    if ($alert)
    {   
        #Find monitor for Alert.
        $monitorname = (get-monitor $alert.monitoringruleid).Name

        #Check if Monitor is found
        if ($monitorname)
        {
            Write-Host "Monitor Found"
            return $monitorname
        }
        else
        {
            #Call FindRuleForAlert
            FindRuleForAlert $AlertName           
        }
    }
    else
        {
        Write-Host "No Alert found"
        }
}
   
Function FindRuleForAlert($AlertName)
{
    $alert = get-alert | where {$_.Name -eq "$AlertName"}
           
    #Find rule for Alert.
    $rulename = (get-rule $alert.monitoringruleid).Name
   
    Write-Host "Rule Found"       
    return $rulename
}
   
   
#Main
 
Initialize
 
FindMonitorOrRuleForAlert "Data Access Service - Windows Service"
 
FindMonitorOrRuleForAlert "Root Management Server Unavailable." 

When we run the above PowerShell script we find the Monitor or Rule name for the  alerts “Data Access Service – Windows Service” and “Root Manager Server Unavailable.

image

 

image

We know have a way to find the Monitor or Rule name for an alert.

Step 2. Export Management where Company Knowledge is saved.

<#
    In this part of the script we are going to export the Management Packs
    and save it in the User's temp folder
#>


Function Initialize
{
     ## Check for OpsMgr shell
    if ((Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.EnterpriseManagement.OperationsManager.Client'}) -eq $null)
    {
        Write-Host "Load OpsMgr Snapin if not loaded" -foregroundcolor red
        LoadSnapin("localhost")
    }
}
     
Function LoadSnapin($RMS)
{
    add-pssnapin "Microsoft.EnterpriseManagement.OperationsManager.Client";
    set-location "OperationsManagerMonitoring::";
    new-managementGroupConnection -ConnectionString:$RMS;
    set-location $RMS;
}


Function ExportMP($MPname, $mpexportfolder)
    {
        #Get Management where Company Knowledge is saved. Must be know in advance.
        get-managementpack | where {$_.Name -eq $MPName} | export-managementpack -path $mpexportfolder
        Write-Host "MP exported to xml"
    }


#Main

Initialize

ExportMP -MPname "Stefan.Company.Knowledge.Test.MP" -mpexportfolder ($env:TEMP)

Result:

image

 

We now exported the Management Pack where we saved the Company Knowledge to the users temp directory.

Step 3. Parse Company Knowledge for Monitor from exported XML MP.

<#
    In this part of the script we are parse the Company Knowledge
    for the Monitor or Rule
#>

#Variables
$monitorname = "Microsoft.Windows.Server.AD.Domain.AvailRollupMonitor"


Function Initialize
{
     ## Check for OpsMgr shell
    if ((Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.EnterpriseManagement.OperationsManager.Client'}) -eq $null)
    {
        Write-Host "Load OpsMgr Snapin if not loaded" -foregroundcolor red
        LoadSnapin("localhost")
    }
}
     
Function LoadSnapin($RMS)
{
    add-pssnapin "Microsoft.EnterpriseManagement.OperationsManager.Client";
    set-location "OperationsManagerMonitoring::";
    new-managementGroupConnection -ConnectionString:$RMS;
    set-location $RMS;
}

Function ParseCK($monitor,$mpexportfolder,$MPName)
{
    $xml =  [xml](Get-Content $mpexportfolder"\"$MPname".xml")
         
    #MonitorName
    $ElementID = "'"+ "$Monitor" + "'"
    $KnowledgeArticle = [xml](Select-Xml -xml $xml -xpath "//KnowledgeArticle[contains(@ElementID, $ElementID)]")
    $myarray = $KnowledgeArticle.MamlContent.section
    $myarray | Format-Table @{Label="Title";Expression={$_.title}}, @{Label="Text";Expression={$_.para}} -aut
    Write-Host "finished"
}
     
#Main
     
Initialize

ParseCK -monitor $monitorname -mpexportfolder ($env:TEMP) -MPName "Stefan.Company.Knowledge.Test.MP"

Result:

image

Or for the Rule:

image

 

Step 4. Email Company Knowledge

In PowerShell 2.0 there is a new cmdlet Send-MailMessage, but I’m going to use the Net.Mail.MailMessage .Net class because my smtp server needs authentication.

<#
    In this part of the script we are emailing the Company Knowledge
#>


#Body
$body = @"
    <h1>Knowledge Article</h1>

    <h2>Summary</h2>

    <h2>Configuration</h2>

    <h2>Causes</h2>

    <h2>Resolutions</h2>

    <h2>Additional Information</h2>

    <h2>External Knowledge Sources</h2>
"@


# Create mail and set priority
$mail = new-object Net.Mail.MailMessage
$mail.Priority = [System.Net.Mail.MailPriority]::High

# Create from, to, and bcc
$mail.From  = opsmgr@stranger.local
$mail.To.Add("username@hotmail.com")
$mail.CC.Add("username@microsoft.com")
$mail.BCC.Add(username@stranger.local)

# Create the message
$mail.Subject = "OpsMgr email with Company Knowledge" + " (" + [System.DateTime]::Now.ToString("yyyy-MM-dd HH:mm") + ")"
$mail.Body = $body
$mail.IsBodyHtml = $true

# Set SMTP Server and create SMTP Client
$smtp = new-object Net.Mail.SmtpClient
$smtp.Host = "mail.stranger.local"
$smtp.Port = "25"
$smtp.EnableSsl = $false
$smtp.Credentials = New-Object System.Net.NetworkCredential(stefan@stranger.local, P@ssw0rd);

# Send message
try {
   $smtp.Send($mail)
}
catch {
  "Exception caught: {0}" -f $Error[0]
}

Result:

image

 

Ok now we only have to put all the separate parts together Winking smile

 

<#
    Pulling OpsMgr Company Knowledge from Management Pack and send it to email.
    This script will find the monitor or rule for a selected alert and
    pull the Company Knowledge for this monitor or rule from the exported Management Pack.
    Tested on:
    - OpsMgr 2007 R2
    - PowerShell version 2.0
    Remark: All the Company Knowledge should be saved in ONE Management Pack
    Author: Stefan Stranger
    Date: 17-02-2011
#>

param($AlertName=(Read-Host "Please Enter Alert Name"),$emailto=(Read-Host "Please Enter email address"))

 

#Variables:
$global:mpname = ""
$global:rmsname = "opsmgrrms.stranger.local"
$global:mpname = "Stefan.Company.Knowledge.Test.MP"
$currentpath = pwd

#Error Handling
#This is because when there is no monitor found in the FindMonitorForAlert Function
#the script needs to continue.
$ErrorActionPreference="SilentlyContinue"
$Error.psbase.clear()

       
Function Initialize
{
     ## Check for OpsMgr shell
    if ((Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.EnterpriseManagement.OperationsManager.Client'}) -eq $null)
    {
        Write-Host "Load OpsMgr Snapin if not loaded" -foregroundcolor red
        LoadSnapin("$rmsname")
    }
}
     
Function LoadSnapin($rmsname)
{
    add-pssnapin "Microsoft.EnterpriseManagement.OperationsManager.Client";
    set-location "OperationsManagerMonitoring::";
    new-managementGroupConnection -ConnectionString:$rmsname;
    set-location $rmsname;
}

Function FindRuleForAlert($AlertName)
{
    $alert = get-alert | where {$_.Name -like "$AlertName"}
   
    $monitoringruleid = ($alert | select MonitoringRuleID -first 1).MonitoringRuleId.Guid
           
    #Find rule for Alert.
    $rulename = (get-rule $monitoringruleid).Name
   
    Write-Host "Rule Found"       
    return $global:monitororrulename = $rulename
}
     
     
Function FindMonitorOrRuleForAlert($AlertName)
{
    #Find an alert with resolution state new
    $alert = get-alert | where {$_.Name -like "$AlertName"}
   
    #Check if Alert is available
    if ($alert)
    {   
       
        $monitoringruleid = ($alert | select MonitoringRuleID -first 1).MonitoringRuleId.Guid
        #Find monitor for Alert.
        $monitorname = (get-monitor $monitoringruleid).Name

        #Check if Monitor is found
        if ($monitorname)
        {
            Write-Host "Monitor Found"
            return $global:monitororrulename = $monitorname
        }
        else
        {
            #Call FindRuleForAlert
            FindRuleForAlert $AlertName           
        }
    }
    else
        {
        Write-Host "No Alert found"
        break
        }
}
   

   
   
 
#Step 2. Export Management where Company Knowledge is saved.
<#
    In this part of the script we are going to export the Management Packs
    and save it in the User's temp folder
#>


Function ExportMP($MPname, $mpexportfolder)
{
    #Get Management where Company Knowledge is saved. Must be know in advance.
    get-managementpack | where {$_.Name -eq $MPName} | export-managementpack -path $mpexportfolder
    Write-Host "MP exported to xml"
}


#Step 3. Parse Company Knowledge for Monitor from exported XML MP.
<#
    In this part of the script we are parse the Company Knowledge
    for the Monitor or Rule
#>

Function ParseCK($monitororrulename,$mpexportfolder,$MPName)
{
    $xml =  [xml](Get-Content $mpexportfolder"\"$MPname".xml")
         
    $ElementID = "'"+ "$monitororrulename" + "'"
    $KnowledgeArticle = [xml](Select-Xml -xml $xml -xpath "//KnowledgeArticle[contains(@ElementID, $ElementID)]")
    $global:myarray = $KnowledgeArticle.MamlContent.section
    #$myarray | Format-Table @{Label="Title";Expression={$_.title}}, @{Label="Text";Expression={$_.para}} -aut
    Write-Host "Parsed Company Knowledge"
}

#Step 4. Email Company Knowledge
<#
    In this part of the script we are emailing the Company Knowledge
#>

$Summary = ($myarray | where {$_.Title -eq "Summary"}).para
$Configuration = ($myarray | where {$_.Title -eq "Configuration"}).para
$Causes = ($myarray | where {$_.Title -eq "Causes"}).para
$Resolutions = ($myarray | where {$_.Title -eq "Resolutions"}).para
$Additional = ($myarray | where {$_.Title -eq "Additional"}).para
$External = ($myarray | where {$_.Title -eq "External"}).para


#Body
$body = @"
    <h1>Knowledge Article</h1>

    <h2>Summary</h2>
    <p>$Summary</P>
    <h2>Configuration</h2>
    <p>$Configuration</P>
    <h2>Causes</h2>
    <p>$Causes</P>
    <h2>Resolutions</h2>
    <p>$Resolutions</P>
    <h2>Additional Information</h2>
    <p></P>
    <h2>External Knowledge Sources</h2>
    <p>$External</P>
"@

Function EmailCK($emailto)
{

    # Create mail and set priority
    $mail = new-object Net.Mail.MailMessage
    $mail.Priority = [System.Net.Mail.MailPriority]::High

    # Create from, to, and bcc
    $mail.From  = "opsmgr@stranger.local"
    $mail.To.Add($emailto)
    $mail.CC.Add("username@microsoft.com")
    $mail.BCC.Add(username@stranger.local)

    # Create the message
    $mail.Subject = "OpsMgr email with Company Knowledge" + " (" + [System.DateTime]::Now.ToString("yyyy-MM-dd HH:mm") + ")"
    $mail.Body = $body
    $mail.IsBodyHtml = $true

    # Set SMTP Server and create SMTP Client
    $smtp = new-object Net.Mail.SmtpClient
    $smtp.Host = "mail.stranger.local"
    $smtp.Port = "25"
    $smtp.EnableSsl = $false
    $smtp.Credentials = New-Object System.Net.NetworkCredential("username@stranger.nl", P@ssword);

    # Send message
    try {
       $smtp.Send($mail)
       Write-Host "Email is sent"
    }
    catch {
      "Exception caught: {0}" -f $Error[0]
    }
}

#Step 5. Clean up
<#
    In this part of the script we are cleaning up.
    Remove the exported MP XML file.
#>

Function CleanUp($MPname)
{
    remove-item ($env:TEMP+"\"+$MPname+".xml")
    Write-Host "Remove MP XML File"
    remove-pssnapin -name "Microsoft.EnterpriseManagement.OperationsManager.Client"
    cd $currentpath
    $AlertName = ""
   

}


#Main
 
Initialize

FindMonitorOrRuleForAlert $AlertName

ExportMP -MPname $mpname -mpexportfolder ($env:TEMP)

ParseCK -monitor $monitororrulename -mpexportfolder ($env:TEMP) -MPName $mpname

EmailCK -emailto $emailto

CleanUp -MPname $mpname

 

Result:

image

 

image

 

Have fun!F

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi Stefan,

    Interesting article.  I think your script would be even better though if you replaced all calls to Write-Host with other Write-* calls like Write-Warning, Write-Error, Write-Verbose, Write-Progress or Write-Debug.  If you want to see what it is doing, Write-Progress is a great cmdlet to allow for progress to be displayed in a script, and it's a better practice to follow than using Write-Host.  If you want some extra information to be available during the execution of the script, maybe to get an idea where it is getting hung up or taking longer, Write-Verbose would be useful.  And of course Write-Warning or Write-Error for anything that is out of the ordinary or unexpected.  I think your readers would benefit from seeing these calls used instead of just Write-Host so that the script could run cleanly without writing anything unnecessary to the main console output.  Write-Host works fine, of course, I just think the other Write-* cmdlets are great to know and more appropriate for most situations where Write-Host is used.

    Kirk out.

  • Nice article,Thanks for sharing.<a href="taskey.com/.../a>