Skip to content
adatum
  • Home
  •  About adatum
  •  Learn Azure Bicep
  •  SCOM Web API
MPAuthoring

SCOM Task to restart Agent – am i complicating…

  • 16/11/201616/11/2016
  • by Martin Ehrnst

As part of planning to migrate a large (3000 + VM) SCOM 2012 R2 environment to 2016 we will need to do a bit of agent configuration. I have created two tasks in Our SCOM console to help us add or delete management Groups from the monitored computers (when moving all agents we probably will use some other orchestration). The problem is that you will have to restart the agents HealthService to save new configuration. Since we execute the task/script through the Health service the task will fail when we attempt to restart. You may experience Your task to work, as in you will have the managment Group added, but you will not see any output.
Over the years People have published a lot of scripts that restarts the agents but unfortunately I have not managed to get them to work properly.

Therfore, i am complicating Things…

I created a script which creates a scheduled task set to run in one minute before it expires and deletes. The Whole thing Works perfectly, but there has to be another way?

<#
NAME: Create-SCOMAgentRestartSchedTask.ps1

.DESCRIPTION
    Creates a scheduled task on the computer which will restart scom health service.
    Script is used as agent task within SCOM as a 'hack' to restart agent through the console.
    
.NOTES
    Martin Ehrnst /Intility AS
    www.adatum.no

    Intial release November 16
    Version 1.0


#>

#Do some logging to the Operations Manager Event Log
$api = new-object -comObject MOM.ScriptAPI
$api.LogScriptEvent("Create-SCOMAgentRestartSchedTask.ps1", 1001, 4, "Creating a scheduled task to restart SCOM health service. Task will expire and delete after it's finished.")

$Service = "HealthService"
$Action = New-ScheduledTaskAction -Execute "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -Argument "Get-Service $Service | restart-service -force"
$run = (Get-Date).AddMinutes(1) # Two minutes from now
$User = 'SYSTEM'
$trigger = New-ScheduledTaskTrigger -Once -At ($run)
$settings = New-ScheduledTaskSettingsSet -DeleteExpiredTaskAfter 00:00:01
Register-ScheduledTask -TaskName "Restart SCOM HealthService" -User $user -InputObject (
  (
    New-ScheduledTask -Action $Action -Trigger $trigger -Settings $settings
) | %{ $_.Triggers[0].EndBoundary = $run.AddMinutes(5).ToString('s') ; $_ })
write-host "created a task to restart $service in one minute"

I know that Microsoft have a recovery action to restart the agent when it is using too much memory and similar, but I haven’t broken Down their code.

taskinfosystemeventlog

Share this:

  • LinkedIn
  • Twitter
  • Reddit
MPAuthoring

OpsMgr & External Services PT2

  • 16/10/2016
  • by Martin Ehrnst

Continuing the series where i try to season Operations Manager with data from external sources. Where In part one I created a CSV file containing the name and url to yr.no’s open XML API. I created two classes and one relationship and discoveries for these. You can find part one of OpsMgr and External services here

In part two, I will continue with the weather management pack focusing on the Health Model by adding rules and monitors to Our location Objects. Full MP and VSAE Project will be included at the end of this post.

The rules are perf. Collection rules which collects the forecasted and observed temperature from yr.no. The monitor is added to alert when observed temperature is below what is set as alert temperature on each location (Object). For the configurable alert temperature I have added a New property to the weather location class.

  <Property ID="LocationName" Key="true" Type="string" />
  <Property ID="LocationURL" Key="false" Type="string" />
  <Property ID="LocationAlertTemp" Key="false" Type="int" />

Which also means that Our discovery script has changed as well With the following line.

$instance.AddProperty("$MPElement[Name='TheWeatherSolution.WeatherLocation']/LocationAlertTemp$",$LocationAlertTemp)

Temperature (perf.) Collection rules

If you explore the API from yr, you will see that you get forecast for different periods. I noticed that when you Access the forecast XML node the first Object will always be for the period youre in right now which makes it easier to Write the script when we could just use the first Object.

An example of how the response:

from          : 2016-10-16T21:00:00
to            : 2016-10-17T00:00:00
period        : 3
#comment      : { Valid from 2016-10-16T21:00:00 to 2016-10-17T00:00:00 ,  Valid at 2016-10-16T21:00:00 }
symbol        : symbol
precipitation : precipitation
windDirection : windDirection
windSpeed     : windSpeed
temperature   : temperature
pressure      : pressure

As i mentioned in part one of this blog series I have gotten tips from Trond Hindenes for the MP it self and Kevin Holman for the VSAE fragments used in PowerShell  rules and monitors. For this MP I created two collection rules for temperatures. Both observed and forcasted temp. (don’t ask, i know this data is available at www.yr.no).

The rules use the similar PS script, and after adding the OpsMgr Magic around it this is how it ended up.

param([string]$LocationURL, [string]$LocationName)
                  
                  # Add the SCOM API and Propertybag for output
                  $api = New-Object -comObject "MOM.ScriptAPI"
                  $bag = $api.CreatePropertyBag()
                  $ScriptName = "GetTemperatureObservation.ps1"

                  # Logging
                  $api.LogScriptEvent($ScriptName,1234,0,"$ScriptName script is starting")
                  
                  [xml]$yr = Invoke-WebRequest -Uri $LocationURL
                  #Getting the latest observation
                  $Observation = $yr.SelectNodes("//observations").weatherstation | Select-Object -First 1
                  [int]$ObservationTemp = $Observation.temperature.value

                  #Adding the value from the script into the propertybag
                  $bag.AddValue("ObservationTemp",$ObservationTemp)
                  #Logging
                  $api.LogScriptEvent($ScriptName,1235,0,"$ScriptName script is complete")

                  #Outputting the bag
                  $bag
                  ]]>

As you see, the script takes location URL as a parameter which needs to be added to the fragment by Kevin if you use it.

                <Parameters>
                  <Parameter>
                    <Name>LocationURL</Name>
                    <Value>$Target/Property[Type="TheWeatherSolution.WeatherLocation"]/LocationURL$</Value>
                  </Parameter>
                </Parameters>

After a few days you hopefully have a graph like this With observed and forecasted temperature

Observed temp vs forecast

 

Monitor

I don’t like having unmonitored Objects in SCOM so we needed to add a monitor to these locations, dont know why i need to be alerted by SCOM when it’s cold out, but now i can. Again, based on Kevins fragment created a two state PowerShell monitor which grabs the LocationAlertTemp parameter from each location and compares it to the observed temperature by yr.no. Anything less than Our Alert Temp will change the state and rase an alert. As you can imagine, no drastic changes to the PowerShell script we used in the rule, but some changes to the SCOM bits. This scipt/monitor takes two parameters that need to be added. First the location URL and the LocationAlertTemp.

                  param([string]$LocationURL,[string]$LocationName,[int]$LocationAlertTemp)
                  # Load MomScript API and PropertyBag function
                  $api = new-object -comObject 'MOM.ScriptAPI'
                  $bag = $api.CreatePropertyBag()

                  #Log script event that we are starting task
                  $api.LogScriptEvent("TooCold.ps1",6789,0, "Starting toocold.ps1 script")

                  [xml]$yr = Invoke-WebRequest -Uri $LocationURL
                  #Getting the latest observation
                  $Observations = $yr.SelectNodes("//observations").weatherstation | select-object -First 1
                  [int]$Obstemperature = $Observations.temperature.value
                  $temperatureUnit = $Observations.temperature.unit
                  if ($Obstemperature -lt $LocationAlertTemp){
                  $bag.AddValue("Result","BadCondition")
                  #$bag.AddValue("Description", "It is freaking cold observed temperature" + "$obstemperature" + "$temperatureUnit")
                  }
                  else{
                  $bag.addvalue("Result","GoodCondition")
                  }
                  $bag

Below the script body I have added,

 <Parameters>
                  <Parameter>
                    <Name>LocationURL</Name>
                    <Value>$Target/Property[Type="TheWeatherSolution.WeatherLocation"]/LocationURL$</Value>
                  </Parameter>
                  <Parameter>
                    <Name>LocationAlertTemp</Name>
                    <Value>$Target/Property[Type="TheWeatherSolution.WeatherLocation"]/LocationAlertTemp$</Value>
                  </Parameter>
                </Parameters>

If everything is working correctly you should have all Your locations monitored, and depending on observed temperature and the alert temp parameter it’s either healthy or in warning state

locationmonitoredalerttemp

locationmonitoredalerttempwarningstate

I have made my MP and VSAE Project available for download here – please note that i do not take any responsibility for this MP and it’s not something i would sell or add to Our Production environment before i have made more testing and cleaned all displaynames, alert text etc. Key file are also excluded.

 

Share this:

  • LinkedIn
  • Twitter
  • Reddit
MPAuthoring

Operations Manager and ‘external’ services pt1 (the weather management…

  • 23/09/201623/09/2016
  • by Martin Ehrnst

This post will be the first in a series of posts covering how you can use System Center Operations Manager (SCOM) With external systems. This is a ‘off work’ Project for me where i try to use several external systems which in some whay communicate or can relate to a workflow running in SCOM.

While writing this, we are on the edge where SCOM 2016 will release shortly, but i will be using 2012 R2 in this series.

 

Now for this first post, i will start to create a maangement pack monitoring the weather conditions for a few locations i chose. I will use yr.no – a service provided by Norwegian Meteorological Institute and NRK.YR.no has a XML API and thats readable by Powershell and then also SCOM.

I remembered Trond Hindenes made a MP for this years ago and i was Lucky to find his blog post about it as well – that made Things alot easier. Thank you. Before we start I would also like to say, if you want do do MP Authoring With Visual studio and Authoring Extensions i suggest you check out Kevin Holmans VSAE fragments. They make a huge difference when trying to understand and create discoveries, monitors etc.- I did not use them when i first started creating this MP

Create the classes and ‘application’

Trond made this easy and i used his model as a spring Board and createt to classes and a relationship. One class will define the “Weather server” the server which is running Our Application. Nothing fancy at all. The Application is a registry key, a string property and a CSV file. I have Limited experience in MP Authoring, but i have created some small MP’s before, using VSAE, Silect MP Author etc. This example will be carried out using VSAE.

This Picture shows how i have organized my management pack project

vsae

As Trond I used registry to define where the Application is installed. Under HKLM\Software\TheWeatherSolution i have a New key called WeatherDB and further a string value, “WeatherDBConfigPath”. The string is a path to where i have created a CSV-file which has the location name and the xml-url from yr.no. Simple comma separated file With headers. Hemsedal is still present as it is the top skiing resort in Norway, especially if youre in to off piste skiing like me.

LocationName,YRnoURL
Hemsedal,http://www.yr.no/place/Norge/Buskerud/Hemsedal/Hemsedal_Skisenter/forecast.xml
Oslo,http://www.yr.no/place/Norway/Oslo/Oslo/Oslo/forecast.xml

using a csv is a chance from Tronds MP. So if you follow both examples trying to create Your own solution, make sure you notice this so you don’t end up scratching Your head without having to:)

Class1, WeatherDB

I created the first class which is based  Windows Local Application. If you want to create this exactly as i have, you willl have to change the base class which default is LocalApplicationComponent. WeatherDB has an extra property called ConfigPath. This property string will have the path to where i placed my CSV file

Code from vsae:

ManagementPackFragment SchemaVersion="2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <TypeDefinitions>
    <EntityTypes>
      <ClassTypes>
        
        <!-- In this section, modify the attributes based on your needs. Ensure the
             Base attribute matches the application you are modeling.
             More information can be found in the Management Pack Development Kit: 
             http://msdn.microsoft.com/en-us/library/ee533867.aspx -->
        <ClassType ID="TheWeatherSolution.WeatherDB" Base="Windows!Microsoft.Windows.LocalApplication" Accessibility="Internal" Abstract="false" Hosted="true" Singleton="false">
          
          <!-- Inside this section, you can add and remove properties as needed.
               More information can be found in the Management Pack Development Kit: 
               http://msdn.microsoft.com/en-us/library/ee533714.aspx -->
      
          <Property ID="ConfigPath" Key="false" Type="string" />

        </ClassType>
      
      </ClassTypes>
    </EntityTypes>
  </TypeDefinitions>
  <LanguagePacks>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>
        
        <!-- This is the string users of the Operations Console and Web Console will see. 
             Descriptions are also helpful when the user is doing a search in the Console. -->
        <DisplayString ElementID="TheWeatherSolution.WeatherDB">
          <Name>Weather server Class</Name>
          <Description>Computers with weather location database</Description>
        </DisplayString>

        <!-- Uncomment the below section if you need to add a user friendly string for each property. -->
        
        <DisplayString ElementID="TheWeatherSolution.WeatherDB" SubElementID="ConfigPath">
          <Name>Configuration Path</Name>
          <Description>The path to where configuration files are stored</Description>
        </DisplayString>
        
      </DisplayStrings>
    </LanguagePack>
  </LanguagePacks>
</ManagementPackFragment>

 

Class2, Weather Locations

Weather locations is a class based on LocalApplicationComponent and has a relationship to my WeatherDB class. Weather locations will be defined in the csv file created earlier. It has two Properties, LocationName and LocationURL +  the inherited Properties from it’s base class and relationship. LoactionName is the key property for this class.

Here is the full fragment from VSAE

<ManagementPackFragment SchemaVersion="2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <TypeDefinitions>
    <EntityTypes>
      <ClassTypes>
        
        <!-- In this section, modify the attributes based on your needs. Ensure the
             Base attribute matches the application you are modeling.
             More information can be found in the Management Pack Development Kit: 
             http://msdn.microsoft.com/en-us/library/ee533867.aspx -->
        <ClassType ID="TheWeatherSolution.WeatherLocation" Base="Windows!Microsoft.Windows.ApplicationComponent" Accessibility="Internal" Abstract="false" Hosted="true" Singleton="false">
          
          <!-- Inside this section, you can add and remove properties as needed.
               More information can be found in the Management Pack Development Kit: 
               http://msdn.microsoft.com/en-us/library/ee533714.aspx -->
    
          <Property ID="LocationName" Key="true" Type="string" />
          <Property ID="LocationURL" Key="false" Type="string" />


        </ClassType>
      
      </ClassTypes>
      <RelationshipTypes>

        <RelationshipType

          ID="TheWeatherSolution.WeatherLocation.Realtionship"

          Base="System!System.Hosting"

          Accessibility="Internal"

          Abstract="false">

          <Source ID="Source" Type="TheWeatherSolution.WeatherDB" />

          <Target ID="Target" Type="TheWeatherSolution.WeatherLocation" />

        </RelationshipType>

      </RelationshipTypes>
    </EntityTypes>
  </TypeDefinitions>
  <LanguagePacks>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>
        
        <!-- This is the string users of the Operations Console and Web Console will see. 
             Descriptions are also helpful when the user is doing a search in the Console. -->
        <DisplayString ElementID="TheWeatherSolution.WeatherLocation">
          <Name>WeatherLocation Class</Name>
          <Description></Description>
        </DisplayString>

        <!-- Uncomment the below section if you need to add a user friendly string for each property. -->
        
        <DisplayString ElementID="TheWeatherSolution.WeatherLocation" SubElementID="LocationName">
          <Name>Location Name</Name>
          <Description>The name of the weather forcast location.</Description>
        </DisplayString>
        <DisplayString ElementID="TheWeatherSolution.WeatherLocation" SubElementID="LocationURL">
          <Name>Location URL</Name>
          <Description>the yr.no URL for this location</Description>
        </DisplayString>
      </DisplayStrings>
    </LanguagePack>
    <LanguagePack ID="NOR" IsDefault="false">
      <DisplayStrings>

        <!-- This is the string users of the Operations Console and Web Console will see. 
             Descriptions are also helpful when the user is doing a search in the Console. -->
        <DisplayString ElementID="TheWeatherSolution.WeatherLocation">
          <Name>WeatherLocation Class</Name>
          <Description></Description>
        </DisplayString>

        <!-- Uncomment the below section if you need to add a user friendly string for each property. -->

        <DisplayString ElementID="TheWeatherSolution.WeatherLocation" SubElementID="LocationName">
          <Name>Location Name</Name>
          <Description>The name of the weather forcast location.</Description>
        </DisplayString>
        <DisplayString ElementID="TheWeatherSolution.WeatherLocation" SubElementID="LocationURL">
          <Name>Location URL</Name>
          <Description>the yr.no URL for this location</Description>
        </DisplayString>
      </DisplayStrings>
    </LanguagePack>
  </LanguagePacks>
</ManagementPackFragment>

Relationships was somewhat New to me, i have cut out the relationship section here. Its located just below the class types section.

<RelationshipTypes>
        <RelationshipType ID="TheWeatherSolution.WeatherLocation.Realtionship"
          Base="System!System.Hosting"
          Accessibility="Internal"
          Abstract="false">
          <Source ID="Source" Type="TheWeatherSolution.WeatherDB" />
          <Target ID="Target" Type="TheWeatherSolution.WeatherLocation" />
        </RelationshipType>
      </RelationshipTypes>

Next step would be to import the MP and see if you have two working discoveries. You can confirm this by using “Discovered Inventory”. Unfortinatly, i forgot to take a screenshot at this stage, but hopefully, after everything is discovered it should look something like this (only not monitored) 🙂

classmonitored

Creating a monitor for the location Objects

My goal With this Project isn’t exactly to do weather forecasting or monitoring – there are a few other Tools for that, but as I said I want to test scom and my capabilities. Other than that, i do not want Objects being unmonitored so i created a “location observation freaking Cold monitor” which will generate an alert when observations og below the configured degree. I set -15 deg. celcius. That’s when Norwegians tend to say. “It’s Cold today”

I found that each loaction on YR had something called Observations. I do knot know, but i assume it more like real time data than forecasting. Each location has a few obeservations from surrounding areas, i chose to select the first one. In Powershell thi is how it looks.

[xml]$yr = Invoke-WebRequest -Uri "http://www.yr.no/sted/Norway/Oslo/Oslo/Oslo/forecast.xml"
$Observations = $yr.SelectNodes("//observations").weatherstation | select-object -First 1
[int]$Obstemperature = $Observations.temperature.value
$temperatureUnit = $Observations.temperature.unit
if ($Obstemperature -lt "-15"){
Write-Host "IT IS FREAKING COLD, $obstemperature $temperatureUnit"}
else{ write-host "youre good"}

In PowerShell it seems to be working. No error handling in this Version thoug

isetest

 

After adding the SCOM bits to my script, this is how it looks

                  param([string]$LocationURL,[string]$LocationName)
                  # Load MomScript API and PropertyBag function
                  $api = new-object -comObject 'MOM.ScriptAPI'
                  $bag = $api.CreatePropertyBag()

                  #Log script event that we are starting task
                  $api.LogScriptEvent("TooCold.ps1",6789,0, "Starting toocold.ps1 script")

                  [xml]$yr = Invoke-WebRequest -Uri $LocationURL
                  #Getting the latest observation
                  $Observations = $yr.SelectNodes("//observations").weatherstation | select-object -First 1
                  [int]$Obstemperature = $Observations.temperature.value
                  $temperatureUnit = $Observations.temperature.unit
                  if ($Obstemperature -lt "15"){
                  $bag.AddValue("Result","BadCondition")
                  #$bag.AddValue("Description", "It is freaking cold observed temperature" + "$obstemperature" + "$temperatureUnit")
                  }
                  else{
                  $bag.addvalue("Result","GoodCondition")
                  }
                  $bag

 

To create the monitor i used Kevin Holmans fragments to and changed the Two state PowerShell fragment to my needs. I will try to go more in detail on this at a later stage, but for now this is all you get:)

The next part will cover how to use a rule or monitor against these locations and invoke another external system based on the status or alert of each Objects.

Share this:

  • LinkedIn
  • Twitter
  • Reddit

Posts navigation

1 2

Popular blog posts

  • Azure Application registrations, Enterprise Apps, and managed identities
  • SCOM 1801 REST API Interfaces
  • Creating Azure AD Application using Powershell
  • Automate Azure DevOps like a boss
  • Multi subscription deployment with DevOps and Azure Lighthouse

Categories

Automation Azure Azure Active Directory Azure Bicep Azure DevOps Azure Functions Azure Lighthouse Azure Logic Apps Azure Monitor Azure Policy Community Conferences CSP Monitoring DevOps Guest blogs Infrastructure As Code Microsoft CSP MPAuthoring OMS Operations Manager Podcast Powershell Uncategorised Windows Admin Center Windows Server

Follow Martin Ehrnst

  • Twitter
  • LinkedIn

RSS feed RSS - Posts

RSS feed RSS - Comments

Microsoft Azure MVP

Martin Ehrnst Microsoft Azure MVP
Adatum.no use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it. Cookie Policy
Theme by Colorlib Powered by WordPress