<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Rob Davies' System Center + Azure Blog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/robdavies/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/robdavies/feed.xml</link>
    <description />
    <lastBuildDate>Tue, 16 Apr 2019 06:15:13 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Monitoring Application Gateway with Azure Log Analytics</title>
      <link>https://docs.microsoft.com/archive/blogs/robdavies/monitoring-application-gateway-with-azure-log-analytics</link>
      <pubDate>Fri, 29 Dec 2017 21:14:52 GMT</pubDate>
      <dc:creator><![CDATA[Rob Davies msft]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/robdavies/?p=495</guid>
      <description><![CDATA[Let’s create an awesome dashboard for monitoring Application Gateway in seconds!

&nbsp;

At...]]></description>
      <content:encoded><![CDATA[<h1><a href="https://msdnshared.blob.core.windows.net/media/2017/12/appgw.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/appgw-1024x683.png" alt="" class="alignnone size-large wp-image-505" width="1024" height="683" /></a></h1>
Let’s create an awesome dashboard for monitoring Application Gateway in seconds!

&nbsp;

At the time of writing, if you look at Application Gateway in the Azure Portal, you’ll see one metric – <strong><a href="https://docs.microsoft.com/en-us/azure/monitoring-and-diagnostics/monitoring-supported-metrics#microsoftnetworkapplicationgateways">Throughput</a></strong>.  Although that’s useful, there’s loads more rich information exposed in the Application Gateway diagnostic logs &amp; we can use Azure Log Analytics to monitor, alert &amp; create some great dashboards.  The purpose of this blog is to show some real-world examples you to keep your finger on the pulse of your Application Gateways.

&nbsp;

There is an <a href="https://docs.microsoft.com/en-us/azure/log-analytics/log-analytics-azure-networking-analytics">out-of-the-box solution for monitoring Application Gateway with Log Analytics</a>, however this blog shows how to search the logs yourself, use the Log Analytics capabilities &amp; build a customized dashboard.
<h1>Importing the dashboard</h1>
I’ve shared an ARM template for this dashboard.  All you have to do is:
<ul>
 	<li>Enable Diagnostic Logging for your Application Gateways (below)</li>
 	<li>Import the ARM template from here: <a href="https://github.com/iamrobdavies/MonitoringExamples/tree/master/ApplicationGateway/Dashboard">https://github.com/iamrobdavies/MonitoringExamples/tree/master/ApplicationGateway/Dashboard</a></li>
</ul>
&nbsp;

That’s it! After importing the dashboard, you’re ready to use it from the <strong>Dashboards</strong> section of the Azure Portal.

&nbsp;

There’s more info about ARM Templates for Dashboards here: <a href="https://docs.microsoft.com/en-us/azure/azure-portal/azure-portal-dashboards-structure">https://docs.microsoft.com/en-us/azure/azure-portal/azure-portal-dashboards-structure</a>

My colleague Marco Dias has blogged an excellent example of this here: <a href="https://blogs.msdn.microsoft.com/madias/2017/09/11/azure-resource-manager-template-for-an-azure-dashboard-with-log-analytics-tiles/">https://blogs.msdn.microsoft.com/madias/2017/09/11/azure-resource-manager-template-for-an-azure-dashboard-with-log-analytics-tiles/</a>.
<h1>Enabling Diagnostic Logging</h1>
Application Gateway exposes 3 types of diagnostic logging, Access, Performance &amp; Firewall, as well as Metrics.  As with all our diagnostic logging, the schema for the log files are documented – Application Gateway at: <a href="https://docs.microsoft.com/en-us/azure/application-gateway/application-gateway-diagnostics">https://docs.microsoft.com/en-us/azure/application-gateway/application-gateway-diagnostics</a>.

&nbsp;

The great thing about using native Azure services like Application Gateway, is that you can stream the diagnostic logs directly into Azure Log Analytics.  This is easily done via the UI, az CLI, PowerShell, REST or ARM template.

&nbsp;

The first step is to make sure your Application Gateway Diagnostic logs are configured to <strong>Send to Log Analytics</strong>.  In the Azure Portal, just navigate to the Application Gateway and click <strong>Diagnostic logs</strong>.  You can enable the logs &amp; select the Log Analytics workspace:

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/appgwdiag.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/appgwdiag-288x300.png" alt="" class="alignnone size-medium wp-image-515" width="288" height="300" /></a>

My preferred way is to enable diagnostic is via an ARM template – this is easier as you can switch it on at deploy time, so you don’t have to remember to do it later.  I’ve posted an example Application Gateway deployment, with Diagnostic Logging to Log Analytics enabled here: <a href="https://github.com/iamrobdavies/MonitoringExamples/tree/master/ApplicationGateway/Dashboard">https://github.com/iamrobdavies/MonitoringExamples/tree/master/ApplicationGateway/Dashboard</a>.

&nbsp;

Note: After enabling diagnostic logging, it may take a little while before it starts showing up in the Log Analytics workspace.  After that initial wait, the logs stream across very quickly.

&nbsp;

The assumption is that the Log Analytics workspace you are using has been upgrade to the new Log Search.  I’ll be using the Analytics portal, which is only available if you have an upgraded workspace.  For more information, see <a href="https://docs.microsoft.com/en-us/azure/log-analytics/log-analytics-log-search-upgrade">https://docs.microsoft.com/en-us/azure/log-analytics/log-analytics-log-search-upgrade</a>.

&nbsp;
<h1>Dashboard Queries</h1>
For reference, I’m documenting each of the Log Analytics queries used for each tile in the dashboard.  Remember, these are simply Log Analytics queries, using the data which is included in the Application Gateway Performance and Access Logs.

<strong> </strong>

<strong>Application Gateway Logging Schema: <a href="https://docs.microsoft.com/en-us/azure/application-gateway/application-gateway-diagnostics">https://docs.microsoft.com/en-us/azure/application-gateway/application-gateway-diagnostics</a></strong>

<strong> </strong>
<h2>Avg throughput per second (Mb)</h2>
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayPerformanceLog"
| summarize avg(throughput_d) by Resource, bin(TimeGenerated, 1m)
| extend ThroughputMb = (avg_throughput_d/1000)/1000
| project Resource, TimeGenerated, ThroughputMb
| render timechart</pre>
&nbsp;
<h2>Unhealthy backend VM count</h2>
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayPerformanceLog"
| summarize max(unHealthyHostCount_d) by Resource, bin(TimeGenerated, 1m)
| render timechart</pre>
&nbsp;
<h2>Healthy backend VM Count</h2>
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayPerformanceLog"
| summarize max(healthyHostCount_d) by Resource, bin(TimeGenerated, 1m)
| render timechart</pre>
&nbsp;
<h2>Failed requests by API</h2>
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayAccessLog"
| where httpStatus_d &gt;= 400
| summarize count() by requestUri_s, bin(TimeGenerated, 1m)
| render timechart</pre>
&nbsp;
<h2>Avg Latency (ms) by AppGW</h2>
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayPerformanceLog"
| summarize avg(latency_d) by Resource, bin(TimeGenerated, 1m)
| render timechart</pre>
&nbsp;
<h2>Requests per Min by API</h2>
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayAccessLog"
| summarize count() by requestUri_s, bin(TimeGenerated, 1m)
| render timechart</pre>
&nbsp;
<h2>MyService API Requests per Min</h2>
<strong>NOTE: </strong>The intention here is that this shows the number of requests for some specific URI, maybe a critical service.

You should modify the clause where <em>requestUri_s == “/”</em> to the URI of the service/API you want to list.

&nbsp;
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayAccessLog"
| where requestUri_s == "/"
| summarize count() by requestUri_s, bin(TimeGenerated, 1m)
| render timechart</pre>
&nbsp;
<h2>Error count past hour by AppGW</h2>
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayAccessLog"
| where httpStatus_d &gt;= 400
| summarize count() by httpStatus_d, Resource
| project httpStatus_d, Resource, count_</pre>
&nbsp;
<h2>Avg Requests per min</h2>
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayPerformanceLog"
| summarize avg(requestCount_d) by Resource, bin(TimeGenerated, 1m)
| render timechart</pre>
&nbsp;
<h2>Avg Failed Requests per min</h2>
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayPerformanceLog"
| summarize avg(failedRequestCount_d) by Resource, bin(TimeGenerated, 1m)
| render timechart</pre>
&nbsp;
<h2>HTTP Error count per hour by API</h2>
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayAccessLog"
| where httpStatus_d &gt;= 400
| summarize count(httpStatus_d) by httpStatus_d,requestUri_s, bin(TimeGenerated, 1h)
| order by count_httpStatus_d desc
| project httpStatus_d, requestUri_s, TimeGenerated, count_httpStatus_d</pre>
&nbsp;
<h2>Successful request count</h2>
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayAccessLog"
| where httpStatus_d &lt; 400
| summarize count() by httpStatus_d, Resource
| project httpStatus_d, Resource, count_</pre>
&nbsp;

&nbsp;
<h2>Failed requests by backend VM</h2>
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayAccessLog"
| where httpStatus_d &gt;= 400
| parse requestQuery_s with * "SERVER-ROUTED=" serverRouted "&amp;" *
| extend httpStatus = tostring(httpStatus_d)
| summarize count() by serverRouted, bin(TimeGenerated, 5m)
| render timechart</pre>
&nbsp;
<h2>Successful requests by backend VM</h2>
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayAccessLog"
| where httpStatus_d &lt; 400
| parse requestQuery_s with * "SERVER-ROUTED=" serverRouted "&amp;" *
| extend httpStatus = tostring(httpStatus_d)
| summarize count() by serverRouted, bin(TimeGenerated, 5m)
| render timechart</pre>
&nbsp;
<h2>HTTP 502 errors by backend VM</h2>
<strong>NOTE: </strong>This is a useful one to help identify where you need to the troubleshooting steps listed here: <a href="https://docs.microsoft.com/en-us/azure/application-gateway/application-gateway-troubleshooting-502">https://docs.microsoft.com/en-us/azure/application-gateway/application-gateway-troubleshooting-502</a>.

&nbsp;
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayAccessLog"
| where httpStatus_d == 502
| parse requestQuery_s with * "SERVER-ROUTED=" serverRouted "&amp;" *
| extend httpStatus = tostring(httpStatus_d)
| summarize count() by serverRouted, bin(TimeGenerated, 5m)
| render timechart</pre>
&nbsp;
<h2>Monitored AppGW List</h2>
<pre>AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayAccessLog"
| distinct Resource, ResourceGroup</pre>]]></content:encoded>
    </item>
    <item>
      <title>Auto Assign SCSM Incidents with Azure Automation</title>
      <link>https://docs.microsoft.com/archive/blogs/robdavies/auto-assign-scsm-incidents-with-azure-automation</link>
      <pubDate>Tue, 12 Jul 2016 14:54:12 GMT</pubDate>
      <dc:creator><![CDATA[Rob Davies msft]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/robdavies/?p=435</guid>
      <description><![CDATA[Have you ever wanted Service Manager to auto assign Incidents to analysts?  This blog talks through...]]></description>
      <content:encoded><![CDATA[<span style="color: #000000;font-family: Calibri">Have you ever wanted Service Manager to auto assign Incidents to analysts?  This blog talks through doing just that!</span><span style="color: #000000;font-family: Calibri"> </span>

<span style="color: #000000;font-family: Calibri">Rather than relying on engineers manually picking up incidents, or have someone assigning them, this solution will automatically assign out incidents, up to a set limit.</span><span style="color: #000000;font-family: Calibri"> </span>

<span style="color: #000000;font-family: Calibri">You can easily schedule this script to run, using Azure Automation.  Using the Hybrid Worker feature, this will run on-premises, against your existing SCSM environment.  No changes or Management Packs required! </span>

<span style="color: #000000;font-family: Calibri">Here’s a walkthrough of what happens:</span>
<ul>
	<li><span style="font: 7.0pt 'Times New Roman'"><span style="color: #000000">       </span></span><span style="color: #000000;font-family: Calibri">New incidents are waiting in the Tier 1 Support Group</span></li>
	<li><span style="font: 7.0pt 'Times New Roman'"><span style="color: #000000">       </span></span><span style="color: #000000;font-family: Calibri">This script runs &amp; looks up who is in an AD Group for the Tier 1 Support Group</span></li>
	<li><span style="font: 7.0pt 'Times New Roman'"><span style="color: #000000">       </span></span><span style="color: #000000;font-family: Calibri">We then look at how many incidents are assigned to each Tier 1 analyst, to see who has the least work</span></li>
	<li><span style="font: 7.0pt 'Times New Roman'"><span style="color: #000000">       </span></span><span style="color: #000000;font-family: Calibri">The incident is assigned to the analyst with the fewest assigned active incidents</span></li>
	<li><span style="font: 7.0pt 'Times New Roman'"><span style="color: #000000">       </span></span><span style="color: #000000;font-family: Calibri">If &gt;1 Analyst have the fewest number of active incidents, it’s assigned to whoever has gone longest since last having an incident assigned</span></li>
	<li><span style="font: 7.0pt 'Times New Roman'"><span style="color: #000000">       </span></span><span style="color: #000000;font-family: Calibri">You can configure a maximum Incident assignment limit, e.g. 10 active incidents per analyst.  If all analysts are full, then incidents wait in the Tier 1 Support Group</span></li>
	<li><span style="font: 7.0pt 'Times New Roman'"><span style="color: #000000">       </span></span><span style="color: #000000;font-family: Calibri">Optionally, you can enable ‘Auto Escalation’. If all Tier 1 analysts are at capacity &amp; there are more unassigned active Tier 1 Incidents, they can be automatically bumped to another support Group, e.g. Tier 2.</span></li>
</ul>
<strong>Step 1:</strong> <strong>Register a Hybrid Worker</strong>

If you haven’t already, make sure you have a Hybrid Worker role installed on-premises, for your Azure Automation account.  This is super easy &amp; documented at <a href="https://azure.microsoft.com/en-us/documentation/articles/automation-hybrid-runbook-worker/">https://azure.microsoft.com/en-us/documentation/articles/automation-hybrid-runbook-worker/</a>.

After you’ve done this, you should see your on-prem worker listed under the ‘Hybrid Worker Groups’ tile in your Azure Automation account:

<a href="https://msdnshared.blob.core.windows.net/media/2016/07/aa1.png"><img class="alignnone size-full wp-image-436" src="https://msdnshared.blob.core.windows.net/media/2016/07/aa1.png" alt="aa1" width="562" height="523" /></a>

<strong>Step 2: PowerShell modules on the Hybrid Worker</strong>

Your Hybrid Worker on-prem, is going to be running this PowerShell script.  It requires the Service Manager &amp; Active Directory PowerShell modules.

Simply install the Service Manager console, on the Hybrid Worker.  This will install the SCSM PowerShell module.

For the AD PowerShell module, open up an Administrative Windows PowerShell &amp; run:

Add-WindowsFeature RSAT-AD-PowerShell

&nbsp;

<strong>Step 3: Configure SCSM Credentials</strong>

Go to your Azure Automation Account &gt; Assets &gt; Credentials

Add in the credentials of an account with access to Service Manager.  This is who the script will be run as.

Here, you can see my account is named <u>contoso-rob</u>

<a href="https://msdnshared.blob.core.windows.net/media/2016/07/aa2.png"><img class="alignnone size-medium wp-image-437" src="https://msdnshared.blob.core.windows.net/media/2016/07/aa2-178x300.png" alt="aa2" width="178" height="300" /></a>

<strong>Step 4: Create + Configure a new PowerShell Runbook</strong>

In your Azure Automation Account, create a new <u>PowerShell</u> based Runbook.  Paste in the PowerShell script which I've placed at the bottom of this blog.

&nbsp;

You’ll want to make a few configuration changes to the script.

<strong>Line 25:</strong> I’m calling my stored credentials.  Change contoso-rob to whatever your SCSM account display Name is, which you made in step 3.

<strong>Line 29:</strong> This is the support Group to monitor for new Incidents to be assigned.  This is the display name of the item in the Support Group list on the Incident form.

<strong>Line 31:</strong> If you enable auto-escalation, this is the support group the Incidents will be moved to.

<strong>Line 33:</strong> The AD Group which defines the Analysis for your support group.  These are the people who will have the incidents automatically assigned to them.  Please note – by default, this recursively gets the AD members.  If you want to switch the recursion off, see line 97 (Get-ADGroupMember).

<strong>Line 35:</strong> The maximum number of active Incidents per analyst.

<strong>Line 37:</strong> Set to $true if you want the auto-escalation feature enabled.

<a href="https://msdnshared.blob.core.windows.net/media/2016/07/aa3.png"><img class="alignnone size-full wp-image-445" src="https://msdnshared.blob.core.windows.net/media/2016/07/aa3.png" alt="aa3" width="937" height="295" /></a>

That’s it – Save &amp; publish your Runbook!

<strong>Step 5: Give it a whirl!</strong>

Run the Runbook from the Azure Automation account to test it out.  When you click run, it’ll ask you for the name of a SCSM Management server. (<em>Hint:</em> You could change this to store it in an Automation Asset!).  Remember, this is an on-prem server, which the Hybrid Worker will communicate to.

Make sure you select your Hybrid worker, to run it on prem!

<a href="https://msdnshared.blob.core.windows.net/media/2016/07/aa4.png"><img class="alignnone size-full wp-image-455" src="https://msdnshared.blob.core.windows.net/media/2016/07/aa4.png" alt="aa4" width="305" height="423" /></a>

<span style="color: #000000;font-family: Calibri">After it’s run, you can have a look at the Job output. This shows the history of which Incidents were assigned, who to &amp; any escalation, or if all analysts are at capacity.</span>

<a href="https://msdnshared.blob.core.windows.net/media/2016/07/aa5.png"><img class="alignnone size-full wp-image-465" src="https://msdnshared.blob.core.windows.net/media/2016/07/aa5.png" alt="aa5" width="901" height="429" /></a>

<strong>Step 6: Schedule it!</strong>

If you’re happy how the Runbook ran, you can schedule it to run regularly.

In Azure Automation, go to the Runbook &gt; Schedules &gt; Add a Schedule.  Set this to whatever you like – I put mine as hourly.

Be sure to set the parameter, with the name of your SCSM Management Server &amp; to Run on the hybrid worker.

<a href="https://msdnshared.blob.core.windows.net/media/2016/07/aa6.png"><img class="alignnone size-full wp-image-475" src="https://msdnshared.blob.core.windows.net/media/2016/07/aa6.png" alt="aa6" width="891" height="815" /></a>

&nbsp;
<blockquote>
<div>#######################################################################################################################
# Assigns active incidents for a particular Support Group to the members of an AD Group
# Author: Rob Davies (Microsoft)
# Disclamer: This program source code is provided "AS IS" without warranty representation or condition of any kind
# either express or implied, including but not limited to conditions or other terms of merchantability and/or
# fitness for a particular purpose. The user assumes the entire risk as to the accuracy and the use of this
# program code.
# Tested with System Center 2012 R2 Service Manager with PowerShell v4
# Name: Assign-SCSMIncidents.ps1
# v1.0 - 7/3/2015 - Initial Release
# v1.1 - 7/12/2016 - Updates for Azure Automation
#######################################################################################################################</div>
<div></div>
<div>param (
[string]$SCSMManagementServer="localhost"
)</div>
<div></div>
<div>if (!(Get-module System.Center.Service.Manager))
{
$scsmRegKey = 'HKLM:\SOFTWARE\Microsoft\System Center\2010\Service Manager\Setup'
Import-Module "$((Get-ItemProperty -Path $scsmRegKey -Name InstallDirectory).InstallDirectory)\PowerShell\System.Center.Service.Manager.psd1" -ErrorAction Stop
}
if (!(Get-module ActiveDirectory)) {import-module ActiveDirectory -ErrorAction Stop }</div>
<div></div>
<div>$smCreds = Get-AutomationPSCredential -Name 'contoso-rob'</div>
<div></div>
<div>#============================================================================
#TODO: Set supportGroup as the DISPLAY NAME of the Support Group to monitor
$supportGroup = "Tier 1"
#TODO: Set escalationGroup as the DISPLAY NAME of the support group to escalate to when the supportGroup is full
$escalationGroup = "Tier 2"
#TODO: Distinguished Name of AD Group and find members:
$ADGroupName = "CN=Tier1,OU=Workshop,DC=contoso,DC=work"
#TODO: Max number of active incidents assigned to operator:
$maxAssignedIncidents = 7
#TODO: Auto-Escalate. If $True enables the ability to esclate to escalationGroup. Either: $True or $False
$autoEscalate = $False
#============================================================================</div>
<div></div>
<div>#Work Item Assigned Relationship Type
$WIAssigned = Get-SCRelationship -Name "System.WorkItemAssignedToUser" -ComputerName $SCSMManagementServer -Credential $smCreds</div>
<div></div>
<div>function whoToAssignTo ($helpdeskUserList) {
#Get the user with the fewest number of active incidents assigned
$numberOfAnalystsWithFewestIncidents=0
$firstUser = $helpdeskUserList | Sort-Object AssignedIncidents | Select-Object -First 1</div>
<div></div>
<div>    #Find out if there are any other users with the same number of active assigned incidents
foreach ($x in $helpdeskUserList) {
if ($x.AssignedIncidents -eq $firstUser.AssignedIncidents) {$numberOfAnalystsWithFewestIncidents++}
}
$availableUser = $helpdeskUserList | Sort-Object AssignedIncidents | Select-Object -First $numberOfAnalystsWithFewestIncidents</div>
<div></div>
<div>    #If there is &gt;1 user with fewest number of assigned active Incidents
if ($availableUser.Count -gt 1){</div>
<div></div>
<div>        #Find the incidents which was last assigned for each user
$recentIncidents = @()
foreach ($x in $availableUser) {
$mostRecentIR = $x.ListOfIncidents | Sort-Object LastAssigned -Descending | select -First 1
$recentIncidents = $recentIncidents + $mostRecentIR
}</div>
<div></div>
<div>        #What if there are multiple users with 0 incidents
if($recentIncidents.Count -gt 0) {
#Find the incident which was assigned the longest time ago. Then find the user who is assigned to this
$mostRecentIRFilter = "Id -eq " + ($recentIncidents | Sort-Object LastAssigned | select -First 1).id
$mostRecentIR = Get-SCClassInstance -Class (Get-SCClass -Name System.WorkItem.Incident -ComputerName $SCSMManagementServer -Credential $smCreds) -Filter $mostRecentIRFilter -ComputerName $SCSMManagementServer -Credential $smCreds
$userLastAssignedAnIncident = Get-SCClassInstance -Id (Get-SCRelationshipInstance -SourceInstance $mostRecentIR -ComputerName $SCSMManagementServer -Credential $smCreds |?{$_.RelationshipId -eq $WIAssigned.Id -and $_.IsDeleted -eq $false}).TargetObject.Id -ComputerName $SCSMManagementServer -Credential $smCreds</div>
<div></div>
<div>            #return the user to assign the incident to
return $userLastAssignedAnIncident
} else {
#If multiple with 0 incidents assigned randomly pick someone
$randomUser = ($availableUser | Get-Random)
$userFilter = "DistinguishedName -eq " + $randomUser.UserDN
$userLastAssignedAnIncident = Get-SCClassInstance -Class (Get-SCClass -Name Microsoft.AD.User -ComputerName $SCSMManagementServer -Credential $smCreds) -Filter $userFilter -ComputerName $SCSMManagementServer -Credential $smCreds</div>
<div></div>
<div>            #return the user to assign the incident to
return $userLastAssignedAnIncident
}} elseif ($availableUser.Count -eq $null) {
#If there is only one user with lowest number of active incidents, then get the user object from SCSM
$userFilter = "DistinguishedName -eq " + $availableUser.UserDN
$userLastAssignedAnIncident = Get-SCClassInstance -Class (Get-SCClass -Name Microsoft.AD.User -ComputerName $SCSMManagementServer -Credential $smCreds) -Filter $userFilter -ComputerName $SCSMManagementServer -Credential $smCreds</div>
<div></div>
<div>        #return the user to assign the incident to
return $userLastAssignedAnIncident
}</div>
<div></div>
<div>}</div>
<div></div>
<div>function populateHelpdeskUserList ($GroupName, $maxIncidentCount) {
#Get the members of the AD Group
#TODO: Currently set to Recursive. Remove -Recursive if direct membership is wanted
$usersGroup = Get-ADGroup -Identity $GroupName | Get-ADGroupMember -Recursive</div>
<div></div>
<div>    #List to store analysts and number of active incidents
$helpdeskUserList = @()</div>
<div></div>
<div>    #Calculate how many active Incidents assigned to each member
foreach ($usr in $usersGroup) {
$IRAssigned = 0#Find the user in SCSM
$userFilter = "UserName -eq " + $usr.SamAccountName
$userCI = Get-SCClassInstance -Class (Get-SCClass -Name System.Domain.User -ComputerName $SCSMManagementServer -Credential $smCreds) -Filter $userFilter -ComputerName $SCSMManagementServer -Credential $smCreds</div>
<div></div>
<div>        #Ensure the user is in SCSM
if($userCI -ne $null) {
#Get Active Incidents assigned to the user
$IDs = (((Get-SCRelationshipInstance -TargetInstance ($userCI) -ComputerName $SCSMManagementServer -Credential $smCreds | ?{$_.RelationshipId -eq $WIAssigned.Id -and $_.IsDeleted -eq $false}).SourceObject | ?{$_.FullName -like "System.WorkItem.Incident*"}).Id)#if user has &gt;0 incidents find count of how many active
if ($IDs -ne $null) {
$assignedIncidents = Get-SCClassInstance -Id $IDs -ComputerName $SCSMManagementServer -Credential $smCreds | ?{$_.Status.Name -eq "IncidentStatusEnum.Active"}
$IRAssigned = $assignedIncidents.Count</div>
<div></div>
<div>                #If user not at capcity for incidents
if ($IRAssigned -lt $maxIncidentCount) {#Get the list of Active Incidents assigned to user and DateTime of when last assigned
$assignedIRToUser = @()
foreach($IR in $assignedIncidents) {
$assignedIR = New-Object PSObject -Property @{
Id = $IR.Id
LastAssigned = (Get-SCRelationshipInstance -SourceInstance $IR -ComputerName $SCSMManagementServer -Credential $smCreds |?{$_.RelationshipId -eq $WIAssigned.Id -and $_.IsDeleted -eq $false}).LastModified
}
$assignedIRToUser = $assignedIRToUser + $assignedIR
}</div>
<div></div>
<div>                        #Add the Incident details for this user to the list
$helpdeskUser = New-Object PSObject -Property @{
UserName = $usr.SamAccountName
UserDN = $usr.distinguishedName
AssignedIncidents = $IRAssigned
ListOfIncidents = ($assignedIRToUser | Sort-Object LastAssigned -Descending)
}
#Add user to list of available engineers
$helpdeskUserList = $helpdeskUserList + $helpdeskUser
}
} else { #If the user has 0 incidents assigned
#Add User to the list with 0 assigned
$helpdeskUser = New-Object PSObject -Property @{
UserName = $usr.SamAccountName
UserDN = $usr.distinguishedName
AssignedIncidents = 0
ListOfIncidents = $null
}
#Add user to list of available engineers
$helpdeskUserList = $helpdeskUserList + $helpdeskUser
}
}
}
return $helpdeskUserList
}</div>
<div></div>
<div>try {
Write-Output "Start Time: $(Get-Date -Format MM-dd-yyyy.HH:mm:ss)"</div>
<div></div>
<div>    #Get a list of all Active Incidents in the Support Group
$activeIncidentsInSupportGroup = Get-SCClassInstance -Class (Get-SCClass -Name System.WorkItem.Incident -ComputerName $SCSMManagementServer -Credential $smCreds) -Filter "Status -eq IncidentStatusEnum.Active" -ComputerName $SCSMManagementServer -Credential $smCreds | ?{$_.TierQueue.DisplayName -eq $supportGroup}
#Find assigned incidents, if there are any active incidents in support group
if ($activeIncidentsInSupportGroup -ne $null) {
$assignedIncidents = (Get-SCRelationshipInstance -SourceInstance ($activeIncidentsInSupportGroup) -ComputerName $SCSMManagementServer -Credential $smCreds | ?{$_.RelationshipId -eq $WIAssigned.Id -and $_.IsDeleted -eq $false}).SourceObject.Name
#Get a list of unassigned Incidents in the Support Group
$unassignedIncidents = $activeIncidentsInSupportGroup | where {$_.Id -notin $assignedIncidents}
}</div>
<div></div>
<div>    Write-Output "Incidents to assign $($unassignedIncidents.Count)"
#If there are Incidents to assign
if($unassignedIncidents.Count -gt 0) {</div>
<div></div>
<div>        #Loop through every unassigned incidents starting with the oldest by created date
foreach ($unassignedIncident in ($unassignedIncidents | Sort-Object CreatedDate)) {</div>
<div></div>
<div>            #Get the current list of users available to assign incidents to
$TheUserList = populateHelpdeskUserList $ADGroupName $maxAssignedIncidents
write-output $TheUserList</div>
<div></div>
<div>            #Get the user to assign this particular incident to
$userToAssignIR = whoToAssignTo $TheUserList</div>
<div></div>
<div>            #Make sure there is a user in the list to assign to
if ($userToAssignIR -ne $null){
New-SCRelationshipInstance -RelationshipClass $WIAssigned -Source $unassignedIncident -Target $userToAssignIR -ComputerName $SCSMManagementServer -Credential $smCreds
write-output "ASSIGNED: $($unassignedIncident.Id) to: $($userToAssignIR.DisplayName)"
} else {
#No available users to assign the incident to
write-output "FULL: No engineers available in $($supportGroup) to to assign incident $($unassignedIncident.Id)"
if ($autoEscalate) {
$unassignedIncident.TierQueue = $escalationGroup
$unassignedIncident | Update-SCClassInstance
write-output "ESCALATED: $($unassignedIncident.Id) to $($escalationGroup)"
} elseif (!$autoEscalate) {
Write-Output "Exiting script as assignment slots are full and auto escalation is disabled"
break
}
}
}
} else {
#No incidents needed to be assigned
write-output "Currently no incidents to assign"
}
}
catch {
Write-Warning "ERROR: Something bad happened!"
$_.Exception.Message
}</div></blockquote>
&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>Ingest Azure Diagnostic logging in Log Analytics (OMS) Part 2</title>
      <link>https://docs.microsoft.com/archive/blogs/robdavies/ingest-azure-diagnostic-logging-in-log-analytics-oms-part-2</link>
      <pubDate>Fri, 24 Jun 2016 22:34:44 GMT</pubDate>
      <dc:creator><![CDATA[Rob Davies msft]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/robdavies/?p=345</guid>
      <description><![CDATA[In part 1 we looked at enable diagnostic logging on Azure resources via the Portal or via...]]></description>
      <content:encoded><![CDATA[In <a href="https://blogs.technet.microsoft.com/robdavies/2016/06/24/ingest-azure-diagnostic-logging-in-log-analytics-oms-part-1/">part 1</a> we looked at enable diagnostic logging on Azure resources via the Portal or via PowerShell.
Now, let’s get this ingested into Log Analytics!

It’s worth noting that the current, up-to-date documentation is at: <a href="https://azure.microsoft.com/en-us/documentation/articles/log-analytics-powershell-azure-diagnostics-json" target="_blank">https://azure.microsoft.com/en-us/documentation/articles/log-analytics-powershell-azure-diagnostics-json</a>/.

OK for this, I’m assuming you’ve got WMF 5 installed on your machine. If you’ve not (where have you been!?) go to <a href="https://www.powershellgallery.com" target="_blank">https://www.powershellgallery.com</a>/ &amp; hit the ‘Get WMF 5.0’ button.

Open up an Administrative PowerShell and make sure you’ve got the up to date AzureRM module:
<pre> Install-Module AzureRM</pre>
Import the OMS module, making sure you’ve got at least version 1.0.8:
<pre> Import-Module AzureRM.OperationalInsights -MinimumVersion 1.0.8</pre>
Login to your Azure Account:
<pre> Login-AzureRmAccount</pre>
Run the command to configure the diagnostic into Log Analytics:
<pre> Add-AzureDiagnosticsToLogAnalyticsUI</pre>
&nbsp;

OK OK. Hold up – let’s talk about this <strong>Add-AzureDiagnosticsToLogAnalyticsUI</strong> cmdlet.
Basically, it’s just like one of those choose your own adventure command line games. Like the ones I used to play on the BBC computer in school… Only this is better 

<strong>Add-AzureDiagnosticsToLogAnalyticsUI</strong> guides you through ingesting those diagnostic logs into Log Analytics.
<h3><span style="text-decoration: underline">Adventure Question 1: Whatcha want to collect?</span></h3>
In part 1, I enabled NSG logging, so let’s grab that by hitting 3:

<a href="https://msdnshared.blob.core.windows.net/media/2016/06/a1.png"><img class="alignnone size-large wp-image-355" src="https://msdnshared.blob.core.windows.net/media/2016/06/a1-1024x365.png" alt="a1" width="1024" height="365" /></a>
<h3><span style="text-decoration: underline"><strong>Adventure Question 2:</strong> </span></h3>
OK you can see that it located my NSG and verified diagnostics were turned on. Awesome.
You can see it’s listed out my NSG here &amp; listed it as number 1. If you had more, you’d see them listed here.
To select my NSG diagnostics to ingest into Log Analytics, I’ll hit 1:

<a href="https://msdnshared.blob.core.windows.net/media/2016/06/a2.png"><img class="alignnone size-large wp-image-365" src="https://msdnshared.blob.core.windows.net/media/2016/06/a2-1024x349.png" alt="a2" width="1024" height="349" /></a>
<h3><span style="text-decoration: underline"><strong>Adventure Question 3:</strong> </span></h3>
Which Log Analytics workspace? I’ve only got one on this Azure Subscription, so it’s listed here.
If you have a few, you can select which one the logging will be ingested into:

<a href="https://msdnshared.blob.core.windows.net/media/2016/06/a3.png"><img class="alignnone size-large wp-image-375" src="https://msdnshared.blob.core.windows.net/media/2016/06/a3-1024x158.png" alt="a3" width="1024" height="158" /></a>

OK – that’s it! You’re done:

<a href="https://msdnshared.blob.core.windows.net/media/2016/06/a4.png"><img class="alignnone size-large wp-image-385" src="https://msdnshared.blob.core.windows.net/media/2016/06/a4-1024x198.png" alt="a4" width="1024" height="198" /></a>

Great – that was too easy right!? All you need to do now is get a cup of tea &amp; after a little bit, you’ll see that diagnostic data show up in Log Analytics!

OK now I had a cuppa, I’ve gone to my Log Analytics portal &amp; clicked Search. I’m going to enter the query to see all the stuff: *

<a href="https://msdnshared.blob.core.windows.net/media/2016/06/a5.png"><img class="alignnone size-full wp-image-395" src="https://msdnshared.blob.core.windows.net/media/2016/06/a5.png" alt="a5" width="524" height="236" /></a>

Sweet!! Under ‘TYPE’ I can now see NetworkSecuritygroups.
I’m going to select it &amp; click apply to make the query: * (Type=NetworkSecuritygroups)

<a href="https://msdnshared.blob.core.windows.net/media/2016/06/a6.png"><img class="alignnone size-full wp-image-405" src="https://msdnshared.blob.core.windows.net/media/2016/06/a6.png" alt="a6" width="432" height="628" /></a>

Et voila! Here ya go!
Note you can see the 2 categories of logging here too, so you can filter down &amp; all that stuff!

You can now do all the normal Log Analytics goodness, like filtering, custom fields, alerting, remediation, saving, queries and building kickass dashboards!

<a href="https://msdnshared.blob.core.windows.net/media/2016/06/a7.png"><img class="alignnone size-large wp-image-415" src="https://msdnshared.blob.core.windows.net/media/2016/06/a7-1024x444.png" alt="a7" width="1024" height="444" /></a>]]></content:encoded>
    </item>
    <item>
      <title>Ingest Azure Diagnostic logging in Log Analytics (OMS) Part 1</title>
      <link>https://docs.microsoft.com/archive/blogs/robdavies/ingest-azure-diagnostic-logging-in-log-analytics-oms-part-1</link>
      <pubDate>Fri, 24 Jun 2016 22:34:06 GMT</pubDate>
      <dc:creator><![CDATA[Rob Davies msft]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/robdavies/?p=285</guid>
      <description><![CDATA[It’s a great Friday! The sun is shining here in San Francisco, there’s a food truck festival in town...]]></description>
      <content:encoded><![CDATA[It’s a great Friday! The sun is shining here in San Francisco, there’s a food truck festival in town <strong>AND</strong> you can now get your Azure diagnostic logging into OMS Log Analytics. Superb!
<h3><strong>WHY</strong></h3>
Let’s say you use Network Security Groups or Azure Application Gateway.  You’ve been able to enable diagnostic logging in Azure for a while.  We can now ingest that logging into Log Analytics, so you can centrally monitor it and do all those beautiful things like alerting, dashboards or auto-remediation.

What I’ll discuss here is formally documented <a href="https://azure.microsoft.com/en-us/documentation/articles/log-analytics-powershell-azure-diagnostics-json/">here</a>, but this is a simple walk-through.

&nbsp;
<h3><strong>WHAT?</strong></h3>
OK, so today, you can ingest diagnostic data into Log Analytics from the following stuff:

-        Azure Automation

-        Key Vault

-        Application Gateway

-        Network Security Group

These write JSON formatted log files out to an Azure storage account. That’s what we can get into Log Analytics.

To be formal, let’s take a look at the Azure Resource Types which we can bring into Log Analytics.  To check them out you can run this from Azure PowerShell:
<pre>Get-AzureRmResourceProvider | Out-GridView

</pre>
<a href="https://msdnshared.blob.core.windows.net/media/2016/06/140.png"><img class="alignnone size-large wp-image-295" src="https://msdnshared.blob.core.windows.net/media/2016/06/140-1024x494.png" alt="1" width="1024" height="494" /></a>

<span style="color: #000000;font-family: Calibri">At the time of writing, you can bring the following into Log Analytics:</span>

<span style="color: #000000;font-family: Calibri">-</span><span style="font: 7.0pt 'Times New Roman'"><span style="color: #000000">        </span></span><span style="font-family: 'Courier New'"><span style="color: #000000">Microsoft.Automation/AutomationAccounts</span></span>

<span style="color: #000000;font-family: Calibri">-</span><span style="font: 7.0pt 'Times New Roman'"><span style="color: #000000">        </span></span><span style="font-family: 'Courier New'"><span style="color: #000000">Microsoft.KeyVault/Vaults</span></span>

<span style="color: #000000;font-family: Calibri">-</span><span style="font: 7.0pt 'Times New Roman'"><span style="color: #000000">        </span></span><span style="font-family: 'Courier New'"><span style="color: #000000">Microsoft.Network/ApplicationGateways</span></span>

<span style="color: #000000;font-family: Calibri">-</span><span style="font: 7.0pt 'Times New Roman'"><span style="color: #000000">        </span></span><span style="font-family: 'Courier New'"><span style="color: #000000">Microsoft.Network/NetworkSecurityGroups</span></span><span style="color: #000000;font-family: Calibri"> </span>

<span style="color: #000000;font-family: Calibri">If you wanted to see where Application Gateways &amp; NGS are defined, we can just dig into the ProviderNamespace above.</span>
<pre>Get-AzureRmResourceProvider -ProviderNamespace Microsoft.Network | Out-GridView</pre>
<span style="color: #000000;font-family: Calibri">I’ve highlighted the two Resource Types in Microsoft.Network which we support in Log Analytics:</span>

<a href="https://msdnshared.blob.core.windows.net/media/2016/06/net.png"><img class="alignnone size-full wp-image-305" src="https://msdnshared.blob.core.windows.net/media/2016/06/net.png" alt="net" width="890" height="863" /></a>
<h3><strong>Enabling Diagnostics via the Portal:</strong></h3>
OK, so now we know what we can ingest into Log Analytics, how to I enable the diagnostic logging?  Well it’s easy, either via PowerShell, or via the Azure Portal.

As an example, I’m going to turn on diagnostic logging for a Network Security Group

I’ve loaded up the NSG I want to ingest logging from &gt; Settings &gt; Diagnostics:

<a href="https://msdnshared.blob.core.windows.net/media/2016/06/oms16.png"><img class="alignnone size-large wp-image-315" src="https://msdnshared.blob.core.windows.net/media/2016/06/oms16-1024x623.png" alt="oms1" width="1024" height="623" /></a>

<span style="color: #000000;font-family: Calibri">Next I can simply switch on the diagnostic logging:</span>

<span style="color: #000000;font-family: Calibri">-</span><span style="font: 7.0pt 'Times New Roman'"><span style="color: #000000">        </span></span><span style="color: #000000;font-family: Calibri">I have to select a storage account to place the logs in.  This has to be in the same Azure region as the NSG</span>

<span style="color: #000000;font-family: Calibri">-</span><span style="font: 7.0pt 'Times New Roman'"><span style="color: #000000">        </span></span><span style="color: #000000;font-family: Calibri">You can see we’ve got 2 separate logs for NSG. Both will be ingested into Log Analytics.</span>

<span style="color: #000000;font-family: Calibri">-</span><span style="font: 7.0pt 'Times New Roman'"><span style="color: #000000">        </span></span><span style="color: #000000;font-family: Calibri">I’ve set the retention to 1 day.  Being as it’ll be in my Log Analytics, I don’t need to keep it longer. However, I could if I needed to</span>

<a href="https://msdnshared.blob.core.windows.net/media/2016/06/diag.png"><img class="alignnone size-full wp-image-325" src="https://msdnshared.blob.core.windows.net/media/2016/06/diag.png" alt="diag" width="586" height="643" /></a>

Done! Pretty simple right?!

&nbsp;
<h3><strong>Enabling diagnostics via PowerShell:</strong></h3>
OK so here’s the deal - not all of the resources have the diagnostics tab in the portal.  This is NBD anyway. Hey PowerShell is the future, so you should use that anyway :)<a href="https://msdnshared.blob.core.windows.net/media/2016/06/ps.png"><img class="alignnone size-large wp-image-335" src="https://msdnshared.blob.core.windows.net/media/2016/06/ps-1024x567.png" alt="ps" width="1024" height="567" /></a>

In the example below I’ve enabled diagnostic logging on an NSG named <strong>vmNSG</strong>.  I’m putting the diagnostic logging into a storage account named <strong>vmrg7033</strong>.  This is the same as the portal steps above.

I also set the logging to be retained for a single day.

Notice, the <strong>ResourceType</strong> is exactly the same as I listed above! So if you wanted to enable diagnostic logging for an Application Gateway, you can simply update this example.

&nbsp;
<pre>Login-AzureRMAccount</pre>
<pre>#Find the Network Security Group by name:</pre>
<pre>$nsg = Find-AzureRmResource -ResourceNameContains "vmNSG" -ResourceType "Microsoft.Network/NetworkSecurityGroups"</pre>
<pre>#find the storage account you want to put the logging into</pre>
<pre>$stg = Find-AzureRmResource -ResourceNameContains "vmrg7033"</pre>
<pre>#enable diagnostic logging</pre>
<pre>Set-AzureRmDiagnosticSetting -ResourceId $nsg.ResourceId -StorageAccountId $stg.ResourceId -Enabled $true -RetentionInDays 1 -RetentionEnabled $true</pre>
<pre>#verify enabled is now True</pre>
<pre>Get-AzureRmDiagnosticSetting -ResourceId $nsg.ResourceId</pre>
&nbsp;

<span style="color: #000000;font-family: Calibri">Now we’ve enable diagnostic logging, let’s have a look at how to get that ingested into Log Analytics – we’ll do <a href="https://blogs.technet.microsoft.com/robdavies/2016/06/24/ingest-azure-diagnostic-logging-in-log-analytics-oms-part-2/">that in part 2</a>!</span>]]></content:encoded>
    </item>
    <item>
      <title>Simple look at OMS Alert Remediation with Runbooks: Part 3</title>
      <link>https://docs.microsoft.com/archive/blogs/robdavies/simple-look-at-oms-alert-remediation-with-runbooks-part-3</link>
      <pubDate>Wed, 20 Apr 2016 18:05:29 GMT</pubDate>
      <dc:creator><![CDATA[Rob Davies msft]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/robdavies/2016/04/20/simple-look-at-oms-alert-remediation-with-runbooks-part-3/</guid>
      <description><![CDATA[Alerting in OMS was recently updated with the GA release. One of the great features this offers is...]]></description>
      <content:encoded><![CDATA[<p>Alerting in OMS was recently updated <a href="https://blogs.technet.microsoft.com/msoms/2016/04/11/oms-alerting-is-now-generally-available/">with the GA release</a>. One of the great features this offers is the ability to automatically trigger an Azure Automation Runbook.</p>
<p>There are already some great blogs out there, but in this series I wanted to take a simple look how this works, now it&#39;s generally available.</p>
<p><a href="/b/robdavies/archive/2016/04/21/simple-look-at-oms-alert-remediation-with-runbooks-part-1.aspx">Part 1 link</a></p>
<p><a href="/b/robdavies/archive/2016/04/21/simple-look-at-oms-alert-remediation-with-runbooks-part-2.aspx">Part 2 link</a></p>
<p>&nbsp;</p>
<h1>Triggering child Runbooks</h1>
<p>In the previous blogs, we saw how to trigger a Runbook from an OMS Alert &amp; read out the alert details.</p>
<p>Over the years, working with Automation tools, like System Center Orchestrator, I&#39;ve become a fan of <span style="text-decoration:underline;"><strong>keeping my Runbooks simple!</strong></span></p>
<p>Having big, monolithic Runbooks might look cool, but they can be a pain to troubleshoot &amp; maintain. Splitting bigger tasks into small Runbooks also brings benefits, such as the ability to reuse!</p>
<p>&nbsp;</p>
<p>In the spirit of this, the model I suggest is:</p>
<ul>
<li>Create a <span style="text-decoration:underline;"><em>Trigger</em></span> Runbook, which is triggered from the OMS Alert</li>
<li>The trigger Runbook can parse the Alert RequestBody &amp; then go and start another Runbook to complete a task</li>
</ul>
<p>Why?</p>
<ul>
<li>If you&#39;ve already got a Runbook which does something, you don&#39;t have to modify it to handle WebhookData input</li>
<li>If you&#39;ve got an existing PowerShell script, you can put it into Azure Automation, without having to alter the parameters</li>
</ul>
<p>&nbsp;</p>
<p>I also think it&#39;s cleaner to separate out the parsing of the alert data &amp; the actual Remediation Runbook.</p>
<h2>Step 1: Create a child Runbook</h2>
<p>This is the Runbook which I want to be triggered by my existing <strong>OMSAlertTrigger </strong>Runbook.</p>
<p>I created a new Runbook called <strong>OMSAlertTriggerChild</strong></p>
<p>&nbsp;</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0043_Simplelooka1.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0043_5F00_Simplelooka1.png" /></p>
<p>&nbsp;</p>
<p>I&#39;ve just created a very basic Runbook, which takes 3 parameters.</p>
<p>Each parameter is simply written out. I saved &amp; Published this Runbook.</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0043_Simplelooka2.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0043_5F00_Simplelooka2.png" /></p>
<p>&nbsp;</p>
<h2>Step 2: Call the child Runbook</h2>
<p>Next, I&#39;ve gone back to <strong>OMSAlertTrigger</strong>. I want to modify this, so it triggers the child Runbook instead of writing out data.</p>
<p>You can see below, I simply needed to call the Runbook <strong>OMSAlertTriggerChild</strong> by name &amp; pass in the 3 parameters it accepts.</p>
<p>You can add it easy from selecting &#39;Runbooks&#39; &gt; Right click &gt; Add to canvas:</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0043_Simplelooka3.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0043_5F00_Simplelooka3.png" /></p>
<p>&nbsp;</p>
<p>You may have noticed I also added in -parallel so it can parse the alerts in parallel!</p>
<p>I then saved &amp; published this Runbook</p>
<p>&nbsp;</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0043_Simplelooka4.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0043_5F00_Simplelooka4.png" /></p>
<p>&nbsp;</p>
<h2>Step 3: Trigger the updated Runbook</h2>
<p>As before, I&#39;ll trigger the Runbook by manually raising event 123 on one of my OMS managed machines. I ran this several times, to rest out multiple alerts:</p>
<p><span style="font-family:Courier New;">Write-EventLog -LogName Application -Source MsiInstaller -EventId 123 -Message &quot;hello&quot;</span></p>
<p>I&#39;ll wait for a moment to get the Alert notification, then check the Runbook Job in the portal.</p>
<p>First thing you&#39;ll notice &ndash; you only see the Job for the <strong>OMSAlertTrigger</strong>, we don&#39;t see a separate job for the child Runbook:</p>
<p>&nbsp;</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0043_Simplelooka5.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0043_5F00_Simplelooka5.png" /></p>
<p>&nbsp;</p>
<p>However, if I look in the output for <strong>OMSAlertTrigger</strong>, I can see it shows me the output from the <strong>OMSAlertTriggerChild</strong> Runbook.</p>
<p>This is a lot simpler &ndash; I don&#39;t have to worry about linking job outputs together. I can simply see the output, although it called my child Runbook:</p>
<p>&nbsp;</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0043_Simplelooka6.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0043_5F00_Simplelooka6.png" /></p>
<p>&nbsp;</p>
<h2>What about Hybrid Runbooks?!</h2>
<p>In case you&#39;ve not seen it, we can use the Hybrid Worker to run the Runbook in your datacenter. This is easy to setup, more info is at <a href="https://azure.microsoft.com/en-us/documentation/articles/automation-hybrid-runbook-worker/">https://azure.microsoft.com/en-us/documentation/articles/automation-hybrid-runbook-worker/</a>.</p>
<p>This is also exposed when we setup an Alert in OMS. In the screenshot you can see this time, I&#39;ve selected to run on <strong>Hybrid Worker</strong> and selected my hybrid workers.</p>
<p>&nbsp;</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0043_Simplelooka7.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0043_5F00_Simplelooka7.png" /></p>
<p>&nbsp;</p>
<p>That&#39;s OK, but <strong>what about the Child Runbook?</strong> Although I&#39;ve clearly indicated I wanted <strong>OMSAlertTrigger</strong> to run on my hybrid worker, where will <strong>OMSAlertTriggerChild</strong> be run? Obviously, I want this to be run on the hybrid worker also.</p>
<p>To test this out, I added a line to my <strong>OMSAlertTriggerChild</strong> Runbook, to write out the name of the machine it&#39;s running on:</p>
<p>&nbsp;</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0043_Simplelooka8.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0043_5F00_Simplelooka8.png" /></p>
<p><strong>Great News!</strong> It triggered my child Runbook on my Hybrid Worker too! <span style="font-family:Wingdings;">J</span></p>
<p>As we can see in the screen below, the <strong>Parent</strong> Runbook Ran on prem. (see &#39;Ran on&#39;).</p>
<p>The <strong>Child</strong> runbook, which wrote the output said it&#39;s running on DC01, which is my on-prem hybrid worker.</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0043_Simplelooka9.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0043_5F00_Simplelooka9.png" /></p>
<p>&nbsp;</p>
<h2>To conclude</h2>
<p>It sometimes makes sense to split up your Runbooks into bitesize pieces. It&#39;s often easier to manage, you may end up re-using parts!</p>
<p>If you trigger a Runbook on a Hybrid Worker &amp; it calls another Runbook &ndash; that child Runbook is Run on the Hybrid worker also.</p>
<p>One final note &ndash; You can run an Azure Automation Runbook from PowerShell, using <a href="https://msdn.microsoft.com/en-us/library/mt603661.aspx">Start-AzureRmAutomationRunbook</a>. This accepts the <strong>RunOn</strong> argument, which allows you to select it to Run on a Hybrid Worker. Let&#39;s say you wanted to trigger one Runbook from another, but have that run on a <em>different</em> Hybrid Worker, then that&#39;s how it could be done.</p>]]></content:encoded>
    </item>
    <item>
      <title>Simple look at OMS Alert Remediation with Runbooks: Part 2</title>
      <link>https://docs.microsoft.com/archive/blogs/robdavies/simple-look-at-oms-alert-remediation-with-runbooks-part-2</link>
      <pubDate>Wed, 20 Apr 2016 18:04:12 GMT</pubDate>
      <dc:creator><![CDATA[Rob Davies msft]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/robdavies/2016/04/20/simple-look-at-oms-alert-remediation-with-runbooks-part-2/</guid>
      <description><![CDATA[Alerting in OMS was recently updated with the GA release. One of the great features this offers is...]]></description>
      <content:encoded><![CDATA[<p>Alerting in OMS was recently updated <a href="https://blogs.technet.microsoft.com/msoms/2016/04/11/oms-alerting-is-now-generally-available/">with the GA release</a>. One of the great features this offers is the ability to automatically trigger an Azure Automation Runbook.</p>
<p>There are already some great blogs out there, but in this series I wanted to take a simple look how this works, now it&#39;s generally available.</p>
<p><a href="/b/robdavies/archive/2016/04/21/simple-look-at-oms-alert-remediation-with-runbooks-part-1.aspx">Link to Part 1</a></p>
<p><a href="/b/robdavies/archive/2016/04/21/simple-look-at-oms-alert-remediation-with-runbooks-part-3.aspx">Link to Part 3</a></p>
<h1>Working with alert data</h1>
<p>In the first blog, we saw how to trigger a Runbook from an OMS Alert.</p>
<p>In this blog, we&#39;ll look at the output data &amp; how to extract useful information.</p>
<h2>Step 1: Reading $WebhookData.RequestBody</h2>
<p>In the last blog, we saw that all the useful info was in $WebhokData.Requestbody.</p>
<p>This looked a little cryptic, something like the below. Probably not what you want to read when sipping your morning coffee <span style="font-family:Wingdings;">J</span></p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0041_Simplelooka1.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0041_5F00_Simplelooka1.png" /></p>
<p>&nbsp;</p>
<p>This is JSON data &amp; we can easily parse this out in our Runbook. However, before we do that, let&#39;s just take a look at this info.</p>
<p>To read it manually, I did the following to make it easier:</p>
<ul>
<li>Copied the $WebhokData.Requestbody info from the Output screen</li>
<li>Pasted it into a Visual Studio Code</li>
<li>Saved as output.json</li>
<li>Formatted the code (Alt Shift F) so it&#39;s easier to read!</li>
</ul>
<p>&nbsp;</p>
<p>Now that&#39;s easier to look at! I&#39;ve highlighted some of the useful bits below:</p>
<ul>
<li>All of the content is inside SearchResults</li>
<li>
<div>In <span style="background-color:lime;">Green</span>, you can see there are 2 main sections:</div>
<ul>
<li>__metadata shows us some metadata about the OMS search</li>
<li>value: This contains the actual event</li>
</ul>
</li>
<li>In <span style="background-color:red;">Red</span> you can see I&#39;ve pulled out specifics, such as the Computer the event was on, the event log, the event ID &amp; we can see the contents in the ParameterXml.</li>
</ul>
<p>&nbsp;</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0041_Simplelooka2.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0041_5F00_Simplelooka2.png" /></p>
<p>&nbsp;</p>
<h2>Step 2: Parsing the RequestBody</h2>
<p>How do we read this JSON data &amp; make use of it in our Runbook? Luckily PowerShell is to the rescue here!</p>
<p>This output is JSON formatted data, so all we need to do, is use the <strong>ConvertFrom-Json</strong> cmdlet.</p>
<p>Next up, I&#39;m going to go back to my <strong>OMSAlertTrigger</strong> Runbook &amp; click Edit.</p>
<p>First up, I will get delete $WebhookData.WebhookName and $WebhookData.RequestHeader, as I don&#39;t care about those right now.</p>
<p>Next, I&#39;ll use <strong>ConvertFrom-Json</strong> to load the RequestBody into a PowerShell object. This makes it much easier to navigate through the JSON.</p>
<p>For example, below we get the converted JSON and put it in <span style="font-family:Courier New;">$alertData</span></p>
<p><span style="font-family:Courier New;">$alertData = ConvertFrom-Json $WebhookData.RequestBody</span></p>
<p>I can now navigate to the EventID using <span style="font-family:Courier New;">$alertData.SearchResults.value.EventID</span></p>
<p>&nbsp;</p>
<p>Before I complete this, I&#39;ve got two scenarios I want to cope with:</p>
<ul>
<li>What if the WebhookData is empty</li>
<li>What if there are more than 1 alerts passed in the results (multiple value tags in the JSON)</li>
</ul>
<p>&nbsp;</p>
<p>Taking this into consideration, here&#39;s my new <strong>OMSAlertTrigger</strong> Runbook. A few notes:</p>
<ul>
<li>Line 5: We check the WebhookData isn&#39;t null. If it is, we write an error</li>
<li>Line 6: Converts the JSON data into a PowerShell object</li>
<li>Line 8: In case there are multiple alerts, we loop through each value in the SearchResults</li>
<li>Line 9: I&#39;ve selected a few elements from the JSON and written them out in a friendly way</li>
</ul>
<p>&nbsp;</p>
<p>Save &amp; Publish the new Runbook!</p>
<p>&nbsp;</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0041_Simplelooka3.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0041_5F00_Simplelooka3.png" /></p>
<h2>Step 3: Trigger the updated Runbook</h2>
<p>As before, I&#39;ll trigger the Runbook by manually raising event 123 on one of my OMS managed machines. I ran this several times, to rest out multiple alerts:</p>
<p><span style="font-family:Courier New;">Write-EventLog -LogName Application -Source MsiInstaller -EventId 123 -Message &quot;hello&quot;</span></p>
<p>I&#39;ll wait for a moment to get the Alert notification, then check the Runbook Job in the portal.</p>
<p>&nbsp;</p>
<p>Now if we look at the Job Output, we can see I raised the event 123 four times on the computer SQL.contoso.work.</p>
<p>The OMS Alert picked this up had occurred 4 times, so triggered the Runbook with al 4 alerts in the Web hook Data.</p>
<p>In the output, we can see that we parsed out each alert &amp; wrote the output in a friendly way:</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0041_Simplelooka4.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0041_5F00_Simplelooka4.png" /></p>
<p>&nbsp;</p>
<p>Great! So, now we know how to trigger the Runbook and read out the alert details in a straightforward way.</p>
<p>What other cool stuff can we do with this capability? That&#39;s what we&#39;ll look at in <a href="/b/robdavies/archive/2016/04/21/simple-look-at-oms-alert-remediation-with-runbooks-part-3.aspx">part 3</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Simple look at OMS Alert Remediation with Runbooks: Part 1</title>
      <link>https://docs.microsoft.com/archive/blogs/robdavies/simple-look-at-oms-alert-remediation-with-runbooks-part-1</link>
      <pubDate>Wed, 20 Apr 2016 18:03:09 GMT</pubDate>
      <dc:creator><![CDATA[Rob Davies msft]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/robdavies/2016/04/20/simple-look-at-oms-alert-remediation-with-runbooks-part-1/</guid>
      <description><![CDATA[Alerting in OMS was recently updated with the GA release. One of the great features this offers is...]]></description>
      <content:encoded><![CDATA[<p>Alerting in OMS was recently updated <a href="https://blogs.technet.microsoft.com/msoms/2016/04/11/oms-alerting-is-now-generally-available/">with the GA release</a>. One of the great features this offers is the ability to automatically trigger an Azure Automation Runbook.</p>
<p>There are already some great blogs out there, but in this series I wanted to take a simple look how this works, now it&#39;s generally available.</p>
<p>This is part 1.</p>
<p><a href="/b/robdavies/archive/2016/04/21/simple-look-at-oms-alert-remediation-with-runbooks-part-2.aspx">link to part 2</a></p>
<p><a href="/b/robdavies/archive/2016/04/21/simple-look-at-oms-alert-remediation-with-runbooks-part-3.aspx">link to part 3</a></p>
<h1>Triggering a simple Runbook</h1>
<p>In this first blog we&#39;ll look at how to create a basic Runbook which is triggered by an OMS Alert.</p>
<p>The Runbook will simply write out the details of the alert.</p>
<h2>Step 1: Create a Runbook</h2>
<p>To start, let&#39;s create the Runbook which we want to be trigged by an alert.</p>
<p>Go to your Automation account &amp; create a new Runbook. Here, I&#39;ve created a PowerShell Workflow Runbook called <strong>OMSAlertTrigger:</strong></p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0037_Simplelooka1.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0037_5F00_Simplelooka1.png" /></p>
<p>&nbsp;</p>
<p>This Runbook will take the alert information as the input. To do that, we need to create an input parameter called <strong>$WebhookData</strong>.</p>
<p>OMS will automatically handle passing the alert detail into the $WebhookData parameter.</p>
<p>This $WebhookData is documented at <a href="https://azure.microsoft.com/en-us/documentation/articles/automation-webhooks/">https://azure.microsoft.com/en-us/documentation/articles/automation-webhooks/</a> if you want to know more.</p>
<p>Essentially, it has 3 bits of information in its payload:</p>
<ul>
<li>WebhookName</li>
<li>RequestHeader</li>
<li>RequestBody</li>
</ul>
<p>&nbsp;</p>
<p>So we can understand what these 3 things are, this first Runbook is just going to write each of them as output.</p>
<p>In my Runbook, I entered the following PowerShell to write out the WebhookData info. Next, I clicked Save and then <strong>Publish.</strong></p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0037_Simplelooka2.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0037_5F00_Simplelooka2.png" /></p>
<p>&nbsp;</p>
<p><strong>NOTE:</strong> I have <span style="text-decoration:underline;">not</span> manually created a Webhook on this Runbook. OMS will do this for me automatically.</p>
<p>&nbsp;</p>
<h2>Step 2: Create an on demand Alert</h2>
<p>OK, now it&#39;s time to trigger the Runbook from an alert!</p>
<p>I&#39;ve already configured OMS to collect the Application event logs from my Windows agents. Therefore, I know I can create an alert, based on anything in this event log.</p>
<p>In case you&#39;re not collecting Event Log data, it&#39;s configured from Settings &gt; Data:</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0037_Simplelooka3.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0037_5F00_Simplelooka3.png" /></p>
<p>&nbsp;</p>
<p>For this example, I want to be able to manually create an event, so I can test my Runbook on demand.</p>
<p>To do this, I&#39;m using the Write-EventLog cmdlet in PowerShell.</p>
<p>Simply, go to any machine which is reporting to your OMS workspace, and run the following PowerShell:</p>
<p><span style="font-family:Courier New;">Write-EventLog -LogName Application -Source MsiInstaller -EventId 123 -Message &quot;hello&quot;</span></p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0037_Simplelooka4.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0037_5F00_Simplelooka4.png" /></p>
<p>Shortly after, I can see this in the OMS Log Search, by running the following query:</p>
<p><strong>Type=Event EventID=123 </strong></p>
<p>And I can see the entries where I&#39;ve created this event manually:</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0037_Simplelooka5.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0037_5F00_Simplelooka5.png" /></p>
<p>&nbsp;</p>
<p>I want to setup an alert for this Event 123. So I click the <strong>Alert</strong> button:</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0037_Simplelooka6.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0037_5F00_Simplelooka6.png" /></p>
<p>Here&#39;s how I&#39;ve configured my alert:</p>
<ul>
<li>You can see I&#39;m checking every 5 minutes</li>
<li>The Threshold is &gt; 0, so this will fire if there are any 123 events</li>
<li>I&#39;ve configured this to send me an email</li>
<li>Finally, you can see I&#39;ve picked out to run my <strong>OMSAlertTrigger</strong> runbook</li>
</ul>
<p>Click Save to activate this alert</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0037_Simplelooka7.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0037_5F00_Simplelooka7.png" /></p>
<p>&nbsp;</p>
<h2>Step 3: Trigger the Alert</h2>
<p>OK! Now we&#39;re ready to see this in action.</p>
<p>I&#39;ll go to one of my OMS Agents and run the following PS to raise event 123 in the event log:</p>
<p><span style="font-family:Courier New;">Write-EventLog -LogName Application -Source MsiInstaller -EventId 123 -Message &quot;hello&quot; </span></p>
<p>Shortly after, I got the email from my alert!</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0037_Simplelooka8.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0037_5F00_Simplelooka8.png" /></p>
<p>&nbsp;</p>
<p>OK so hopefully this will have trigged our Runbook! To see this:</p>
<ul>
<li>Go to your Automation Account in the portal</li>
<li>Click on the <strong>Jobs</strong> tile:</li>
</ul>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0037_Simplelooka9.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0037_5F00_Simplelooka9.png" /></p>
<ul>
<li>
<div>You should be able to see the <strong>OMSAlertTrigger</strong> has run:</div>
<p>&nbsp;</p>
</li>
</ul>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0037_Simplelooka10.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0037_5F00_Simplelooka10.png" /></p>
<p>&nbsp;</p>
<ul>
<li>Click this job to see the details</li>
</ul>
<p>&nbsp;</p>
<p>In the details of this Job, we can see it completed successfully.</p>
<p>Click <strong>Output</strong> to see what our Runbook Wrote out:</p>
<p>&nbsp;</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/042116_0037_Simplelooka11.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/042116_5F00_0037_5F00_Simplelooka11.png" /></p>
<p>&nbsp;</p>
<p>Remember, the Runbook wrote out the following:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;Write-Output $WebhookData.WebhookName</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;Write-Output $WebhookData.RequestHeader</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;Write-Output $WebhookData.RequestBody</p>
<p>That&#39;s what we can see in the screenshot above.</p>
<ul>
<li>WebhookName: Not that useful for us</li>
<li>RequestHeader: Can see some information in there from the header. Again, not that useful</li>
<li>RequestBody (in the red square): This is useful! This is all of the detail from the alert!</li>
</ul>
<p>&nbsp;</p>
<p>So you may be thinking that all that info looks a little cryptic! Don&#39;t worry, that&#39;s what we&#39;ll look at in <a href="/b/robdavies/archive/2016/04/21/simple-look-at-oms-alert-remediation-with-runbooks-part-2.aspx">Part 2</a>&hellip;</p>]]></content:encoded>
    </item>
    <item>
      <title>Service Manager portable module for SMA/Azure Automation</title>
      <link>https://docs.microsoft.com/archive/blogs/robdavies/service-manager-portable-module-for-smaazure-automation</link>
      <pubDate>Thu, 14 May 2015 08:29:00 GMT</pubDate>
      <dc:creator><![CDATA[Rob Davies msft]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/robdavies/2015/05/14/service-manager-portable-module-for-smaazure-automation/</guid>
      <description><![CDATA[UPDATE: Since writing this, the PowerShell gallery is available at...]]></description>
      <content:encoded><![CDATA[<p><span style="color:#ff0000;"><strong>UPDATE: <span style="color:#000000;">Since writing this, the PowerShell gallery is available at https://www.powershellgallery.com. There&#39;s a great SCSM module, which you can deploy directly to Azure Automation @ https://www.powershellgallery.com/packages/ScsmPx. </span></strong></span></p>
<p></p>
<p>If you&#39;re using SMA, you&#39;ve probably noticed there are many modules imported for you out-of-the-box. Among others, this includes modules for some of the System Center components: Configuration Manager, Data Protection Manager, Operations Manager, Virtual Machine Manager &amp; SPF.</p>
<p>However, in SMA, there is no module for Service Manager by default. This isn&#39;t a big deal, as your PowerShell workflows can still run Service Manager cmdlets, as long as you install the Service Manager console (which includes the PowerShell module) on the Runbook Worker.</p>
<p>The benefit of having the PowerShell module imported into SMA or Azure Automation as an asset is simple &ndash; the Service Manager cmdlets are shown alongside all of the other activities in the UI. The module is used only to make the authoring experience easier, giving benefits such as storing a Service Manager credential as an asset in SMA or Azure Automation.</p>
<p>One thing to note &ndash; this is NOT the whole Service Manager PowerShell module, but the <strong>portable module.</strong> This basically means that we define what cmdlets are available in the module &amp; store credentials, but don&#39;t actually copy any of the resources over. Remember, this is just used to show the activities in the authoring experience. There&#39;s more information about Portable Modules at <a href="/b/orchestrator/archive/2013/11/04/service-management-automation-portable-modules-what-why-and-how.aspx">http://blogs.technet.com/b/orchestrator/archive/2013/11/04/service-management-automation-portable-modules-what-why-and-how.aspx</a>.</p>
<p>I created the portable module, using the <strong>New-SmaPortableModule</strong> command, which is part of the SMA PowerShell module. I&#39;ve attached it to this blog post, so you can simply import it, rather than having to roll your own. This was created in a Service Manager 2012 R2 UR5 environment.</p>
<p>&nbsp;</p>
<h2>Importing the Module in SMA</h2>
<p>To import the Service Manager Module via the Azure Pack site, go to Automation &gt; Assets &gt; Import Module. You can simply upload the .zip file attached to this blog.</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/051415_1518_ServiceMana1.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/051415_5F00_1518_5F00_ServiceMana1.png" /></p>
<p>&nbsp;</p>
<h2>Importing the Module in Azure Automation</h2>
<p>From the Azure Automation blade, you can go to Assets &gt; Modules &gt; Add a Module. Upload the zip file attached to this blog.</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/051415_1518_ServiceMana2.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/051415_5F00_1518_5F00_ServiceMana2.png" /></p>
<p>&nbsp;</p>
<p>The module takes several minutes to be extracted and imported. After a few minutes, you&#39;ll see the Service Manager activities available to use in your Runbooks.</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/051415_1518_ServiceMana3.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/051415_5F00_1518_5F00_ServiceMana3.png" /></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/telligent.evolution.components.attachments/01/9434/00/00/03/64/95/60/System.Center.Service.Manager-Portable.zip" original-url="http://blogs.technet.com/cfs-filesystemfile.ashx/__key/telligent-evolution-components-attachments/01-9434-00-00-03-64-95-60/System.Center.Service.Manager_2D00_Portable.zip">System.Center.Service.Manager-Portable.zip</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Who is connected to Service Manager?</title>
      <link>https://docs.microsoft.com/archive/blogs/robdavies/who-is-connected-to-service-manager</link>
      <pubDate>Tue, 28 Oct 2014 05:01:44 GMT</pubDate>
      <dc:creator><![CDATA[Rob Davies msft]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/robdavies/2014/10/28/who-is-connected-to-service-manager/</guid>
      <description><![CDATA[I&#39;ve been asked a few times recently how to identify who is connected to a Service Manager...]]></description>
      <content:encoded><![CDATA[<p>I&#39;ve been asked a few times recently how to identify <em>who</em> is connected to a Service Manager Management Server. There are several ways to get the list of users currently connected, so I thought I&#39;d share some of them here.</p>
<p><strong>First up &ndash; How MANY users are connected?</strong></p>
<p>Before we look at how to see who is connected to a Management Server, I wanted to look at how to simply see how many people are connected. The easiest way to do this is from perfmon on the Management Server.</p>
<p>Using the counter OpsMgr SDK Service\Client Connections Using Cache. This will give you read of connections to the Data Access Service in real time.</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/102814_1159_Whoisconnec1.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/102814_5F00_1159_5F00_Whoisconnec1.png" /></p>
<p>&nbsp;</p>
<p><strong>OPTION 1 &ndash; Using the SCOM PowerShell Module </strong></p>
<p>Operations Manager has a nifty &amp; simple way of getting the currently connected users via PowerShell. Unfortunately, this same functionality isn&#39;t available in the Service Manager PowerShell interface. However, due to the shared infrastructure in System Center, we can actually use the Operations Manager shell to query Service Manager.</p>
<p>Whenever you install the Operations Manager console, you&#39;ll also get the &quot;Operations Manager Shell&quot;. This will open up the Operations Manager PowerShell module and connect to your Operations Manager Management Server.</p>
<p>First, we can disconnect from Operations Manager, then point it at a Service Manager Management Server instead. We can then simply query for the list of connected users:</p>
<p>Get-SCOMManagementGroupConnection | Remove-SCOMManagementGroupConnection</p>
<p>New-SCOMManagementGroupConnection -ComputerName <span style="text-decoration:underline;">SERVICEMANAGERSERVER</span></p>
<p>(Get-SCOMManagementGroup).GetConnectedUserNames()</p>
<p>&nbsp;</p>
<p>This will give us the list of the currently logged on users to a Service Manager Management Server:</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/102814_1159_Whoisconnec2.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/102814_5F00_1159_5F00_Whoisconnec2.png" /></p>
<p>&nbsp;</p>
<p><strong>OPTION 2 &ndash; Using .Net </strong></p>
<p>Alternatively we can use the .Net interface into Service Manager. This is an updated version of what&#39;s been previously posted at <a href="/b/servicemanager/archive/2010/02/01/getting-a-list-of-connected-users.aspx">http://blogs.technet.com/b/servicemanager/archive/2010/02/01/getting-a-list-of-connected-users.aspx</a>, as many folks had a problem running it.</p>
<p>Here we&#39;re using the <span style="color:black;font-family:Consolas;font-size:9pt;background-color:white;">GetConnectedUserNames</span> method on the <span style="color:#2b91af;font-family:Consolas;font-size:9pt;background-color:white;">EnterpriseManagementGroup</span> class, as per <a href="http://msdn.microsoft.com/en-us/library/gg460200.aspx">http://msdn.microsoft.com/en-us/library/gg460200.aspx</a>.</p>
<p>&nbsp;</p>
<p><span style="color:black;font-family:Consolas;font-size:9pt;background-color:white;"> <span style="color:#2b91af;">EnterpriseManagementGroup<span style="color:black;"> emg = <span style="color:blue;">new<span style="color:black;"> <span style="color:#2b91af;">EnterpriseManagementGroup<span style="color:black;">(managementServer); </span></span></span></span></span></span></span></p>
<p><span style="color:black;font-family:Consolas;font-size:9pt;background-color:white;"> <span style="color:blue;">foreach<span style="color:black;"> (<span style="color:#2b91af;">String<span style="color:black;"> userName <span style="color:blue;">in<span style="color:black;"> emg.GetConnectedUserNames()) </span></span></span></span></span></span></span></p>
<p><span style="color:black;font-family:Consolas;font-size:9pt;background-color:white;"> { </span></p>
<p><span style="color:black;font-family:Consolas;font-size:9pt;background-color:white;"> <span style="color:#2b91af;">Console<span style="color:black;">.WriteLine(userName.ToString()); </span></span></span></p>
<p><span style="color:black;font-family:Consolas;font-size:9pt;"><span style="background-color:white;"> }</span> </span></p>
<p>&nbsp;</p>
<p>I&#39;ve attached a Visual Studio project, which includes the SMConnections.exe which is ready to run.</p>
<p>You can run: &quot;SMConnections.exe&quot; from the command line, which will default to localhost to run on the Management Server. Alternatively you can run &quot;SMConnections.exe SERVERNAME&quot; to remotely connect to a Management Server.</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/102814_1159_Whoisconnec3.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/102814_5F00_1159_5F00_Whoisconnec3.png" /></p>
<p>&nbsp;</p>
<p><strong>OPTION 3 &ndash; Using Orchestrator </strong></p>
<p>Another way we can do this is in Orchestrator, using the &#39;Run .Net Script&#39; activity.</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/102814_1159_Whoisconnec4.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/102814_5F00_1159_5F00_Whoisconnec4.png" /></p>
<p>In the &#39;Initialize Data&#39; activity, I&#39;ve created 1 string input, called managementServer.</p>
<p>In &#39;Run .Net Script&#39;, I set the language to C# and input the following:</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/102814_1159_Whoisconnec5.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/102814_5F00_1159_5F00_Whoisconnec5.png" /></p>
<p>Note, I&#39;ve looped through the users, adding each to a variable called userNameList, separating each with a comma and space.</p>
<p>On the advanced tab, I&#39;ve added in the reference &amp; Namespaces. You&#39;ll have to point to the Service Manager SDK binary, which is available at C:\Program Files\Microsoft System Center 2012 R2\Service Manager\SDK Binaries\Microsoft.EnterpriseManagement.Core.dll. We&#39;re using the namespaces &#39;System&#39; and &#39;Microsoft.EnterpriseManagement&#39;.</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/102814_1159_Whoisconnec6.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/102814_5F00_1159_5F00_Whoisconnec6.png" /></p>
<p>Finally, I&#39;ve published out the userNameList variable from the code:</p>
<p><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/102814_1159_Whoisconnec7.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/102814_5F00_1159_5F00_Whoisconnec7.png" /></p>
<p>The final activity can write the output however you like. I used a &#39;Send platform event&#39;, but it&#39;d be a good idea to write to a log, DB, etc.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/telligent.evolution.components.attachments/01/9434/00/00/03/64/01/36/SMConnections.zip" original-url="http://blogs.technet.com/cfs-filesystemfile.ashx/__key/telligent-evolution-components-attachments/01-9434-00-00-03-64-01-36/SMConnections.zip">SMConnections.zip</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Working with Lists in Service Manager</title>
      <link>https://docs.microsoft.com/archive/blogs/robdavies/working-with-lists-in-service-manager</link>
      <pubDate>Mon, 20 Oct 2014 11:52:42 GMT</pubDate>
      <dc:creator><![CDATA[Rob Davies msft]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/robdavies/2014/10/20/working-with-lists-in-service-manager/</guid>
      <description><![CDATA[In Service Manager, we can easily configure Lists from the console.  This allows you to ensure all...]]></description>
      <content:encoded><![CDATA[<p>In Service Manager, we can easily configure Lists from the console.  This allows you to ensure all the drop-down lists across forms contain the right values for your organization.
</p><p>For example, the &#39;Incident Classification&#39; list can be altered to include &#39;Facilities Problems&#39; or &#39;Mobile Device Problems&#39;.  
</p><p>I&#39;ve had a few questions recently, asking where the customizations to your lists are stored.  This blog will explain how to find that out.
</p><p>
 </p><p><strong>#1 – Where is the List defined?
</strong></p><p>Let&#39;s look at the Incident Lists as an example.  From the Lists, we can see which Management Pack these are stored in:
</p><p><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/102014_1950_Workingwith1.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/102014_5F00_1950_5F00_Workingwith1.png" alt=" " /><span style="color:#1f497d;">
		</span></p><p>We can see that this is a Sealed Management Pack:
</p><p><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/102014_1950_Workingwith2.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/102014_5F00_1950_5F00_Workingwith2.png" alt=" " />
	</p><p>
 </p><p>If you export the Incident Management Library (System.WorkItem.Incident.Library.xml) file, this is what you&#39;ll see:
</p><p>        &lt;EnumerationValue ID=&quot;IncidentTierQueuesEnum&quot; Accessibility=&quot;Public&quot; /&gt;
</p><p>        &lt;EnumerationValue ID=&quot;IncidentClassificationEnum&quot; Accessibility=&quot;Public&quot; /&gt;
</p><p>        &lt;EnumerationValue ID=&quot;IncidentResolutionCategoryEnum&quot; Accessibility=&quot;Public&quot; /&gt;
</p><p>This MP defines that there are some lists, such as the Incident Classification. <span style="text-decoration:underline;"><strong>HOWEVER</strong></span> there is no contents of the list in this Management Pack.  Basically, this MP has created some lists, but not populated them with anything.
</p><p>
 </p><p><strong>#2 – Where is the List contents?</strong>
	</p><p>In this case, we <em>know</em> that out of the box, the Incident Classification list does contain some items.  So where are they?  There are a few ways to do this (look through the MP XML, PowerShell), but I&#39;m using SQL here
</p><p>The query below can be run against the ServiceManager database.  All you need to do is replace <strong>Incident Classification</strong> with the display name of the List from the Service Manager console.  For example, you could replace with <strong>Service Request Support Group</strong>.
</p><p>
 </p><p><span style="font-family:Consolas;font-size:9pt;"><span style="color:blue;">select</span> EnumTypeName<span style="color:gray;">,</span> lt<span style="color:gray;">.</span>LTValue<span style="color:gray;">,</span> mp<span style="color:gray;">.</span>MPName<span style="color:gray;">,</span> mp<span style="color:gray;">.</span>MPFriendlyName
</span></p><p><span style="font-family:Consolas;font-size:9pt;"><span style="color:blue;">from</span> enumtype et
</span></p><p><span style="font-family:Consolas;font-size:9pt;"><span style="color:gray;">JOIN</span> LocalizedText lt <span style="color:blue;">on</span>
		</span></p><p><span style="font-family:Consolas;font-size:9pt;">lt<span style="color:gray;">.</span>ElementName <span style="color:gray;">=</span> et<span style="color:gray;">.</span>EnumTypeName
</span></p><p><span style="font-family:Consolas;font-size:9pt;"><span style="color:gray;">JOIN</span> ManagementPack mp <span style="color:blue;">on</span>
		</span></p><p><span style="font-family:Consolas;font-size:9pt;">mp<span style="color:gray;">.</span>ManagementPackId <span style="color:gray;">=</span> et<span style="color:gray;">.</span>ManagementPackId
</span></p><p><span style="font-family:Consolas;font-size:9pt;"><span style="color:blue;">where</span> lt<span style="color:gray;">.</span>LanguageCode <span style="color:gray;">=</span>
			<span style="color:red;">&#39;ENU&#39;</span>
		</span></p><p><span style="font-family:Consolas;font-size:9pt;"><span style="color:gray;">and</span> lt<span style="color:gray;">.</span>LTStringType <span style="color:gray;">=</span> 1
</span></p><p><span style="font-family:Consolas;font-size:9pt;"><span style="color:gray;">and</span> et<span style="color:gray;">.</span>ParentEnumTypeId <span style="color:gray;">=<span style="color:blue;">
					<span style="color:gray;">(</span>
				</span></span></span></p><p><span style="font-family:Consolas;font-size:9pt;"><span style="color:blue;">select</span> et<span style="color:gray;">.</span>EnumTypeId <span style="color:blue;">from</span> LocalizedText lt
</span></p><p><span style="font-family:Consolas;font-size:9pt;"><span style="color:gray;">JOIN</span> EnumType et <span style="color:blue;">on</span>
		</span></p><p><span style="font-family:Consolas;font-size:9pt;"><span style="color:gray;">(</span>et<span style="color:gray;">.</span>EnumTypeName <span style="color:gray;">=</span> lt<span style="color:gray;">.</span>elementname<span style="color:gray;">)</span>
		</span></p><p><span style="font-family:Consolas;font-size:9pt;"><span style="color:blue;">WHERE</span> lt<span style="color:gray;">.</span>LTValue <span style="color:gray;">=</span>
			<span style="color:red;">&#39;<span style="background-color:yellow;">Incident Classification</span>&#39;</span>
		</span></p><p><span style="font-family:Consolas;font-size:9pt;"><span style="color:gray;">AND</span> lt<span style="color:gray;">.</span>LTStringType <span style="color:gray;">=</span> 1
</span></p><p><span style="font-family:Consolas;font-size:9pt;"><span style="color:gray;">AND</span> lt<span style="color:gray;">.</span>LanguageCode <span style="color:gray;">=</span>
			<span style="color:red;">&#39;ENU&#39;<span style="color:gray;">)</span>
			</span></span></p><p><span style="font-family:Consolas;font-size:9pt;"><span style="color:gray;">and</span> et<span style="color:gray;">.<span style="color:blue;">Enabled</span> =</span> 1
</span></p><p><span style="font-family:Consolas;font-size:9pt;"><span style="color:blue;">order</span>
			<span style="color:blue;">by</span> et<span style="color:gray;">.</span>Ordinal
</span></p><p>
 </p><p>In the output we can see all of the items in the list, their display name and the Name of the MP they are stored in:
</p><p><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/102014_1950_Workingwith3.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/102014_5F00_1950_5F00_Workingwith3.png" alt=" " />
	</p><p>Note – the ones with the EnumTypeName which are Enum.{GUID} are items generated via the Service Manager console.  The others are out-of-the-box.
</p><p>Here, we can see that the list Items are stored in the Service Manager Incident Management Configuration Library (ServiceManager.IncidentManagement.Configuration.xml) MP.  Of course, as we&#39;re updating this in the console, the MP is unsealed:
</p><p><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/102014_1950_Workingwith4.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/102014_5F00_1950_5F00_Workingwith4.png" alt=" " />
	</p><p><strong>#3 – Why are they in that MP?</strong>
	</p><p>You may notice, when you edit the Incident Classification List, it <em>just works</em>. I.e. It doesn&#39;t ask you where you want to store you custom list items.
</p><p>The reason is:
</p><ul><li>The List is defined in the SEALED MP we identified in step 1
</li><li>Out-of-the-box, that list has got items added to it.  They have already been stored in UNSEALED MP from step 2.
</li><li>Therefore, all future additions to the list will go in the same MP as step 2.  You&#39;ve no control over that from the UI.
</li></ul><p>
 </p><p>You may notice that sometimes when you edit a list, you get a pop-up, asking which MP to store the list contents in:
</p><p><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/34/metablogapi/102014_1950_Workingwith5.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-34-metablogapi/102014_5F00_1950_5F00_Workingwith5.png" alt=" " />
	</p><p>
 </p><p>This happens for 1 of 2 reasons:
</p><ul><li>The List was defined in a sealed MP &amp; hasn&#39;t been extended yet.  Therefore you have to select the unsealed MP to use.  This is a one-time thing, then all items will go in the same unsealed MP.
</li><li>The list may already have items in it, but they are inside of a sealed MP.  Therefore, your extensions will need to be in an unsealed MP.  Again, this is a one-time selection.</li></ul>]]></content:encoded>
    </item>
  </channel>
</rss>