PI Services

Le blog des collaborateurs de PI Services

Script - Suivi des machines ayant l'agent Scom et l'agent Zabbix

Pour faire suite a l'article recent "SCOM - Zabbix - Management Pack pour l'agent Zabbix sur Windows" qui propose de créer et decouvrir une classe 'ZabbixAgent', voici un script permettant de faire un suivi des machines ayant l'agent Scom et l'agent Zabbix.

 

ScomAndZabbix.ps1 (1,20 kb)

 

## RETRIEVE COMPUTERS THAT HAVE SCOM AGENT AND ZABBIX AGENT


#Variables
$MGroup = "MyMG"
$MS= "MyMGServer.mydomain"
$cred = Get-Credential "ME\Myself"


#Import du module SCOM
try
{
Import-Module -Name OperationsManager -ErrorAction stop
}
catch
{
write-host -ForegroundColor red "Erreur lors de l'import du module SCOM"
}

#Connection au management group $MGroup
New-SCOMManagementGroupConnection -ComputerName $MS -Credential $cred



# Classe des "Health Service"
$AgentClass = Get-SCOMClass -DisplayName "Health Service"

# Classe des "Zabbix Agent"
$ZabbAgClass = Get-SCOMClass -DisplayName "ZabbixAgent"

# Instances de la classe $AgentClass
$AgentInst = $AgentClass | Get-SCOMClassInstance | select -Property *

# Instances de la classe $ZabbAgClass
$ZabbAgInst = $ZabbAgClass | Get-SCOMClassInstance | select -Property *


# COMPARAISON (MACHINE AYANT L'AGENT ZABBIX ET L'AGENT SCOM)
$ScomAndZab =  Compare-Object -ReferenceObject $AgentInst.displayname -DifferenceObject $ZabbAgInst.path -IncludeEqual -ExcludeDifferent
Write-Host "--- MANAGEMENT GROUP SCOM: $MS ---"
write-host "--- "$ScomAndZab.count" COMPUTERS THAT HAVE SCOM AND ZABBIX ---"
$ScomAndZab.inputobject | sort

 

SCOM - Zabbix - Management Pack pour l'agent Zabbix sur Windows

 Dans le cadre de la supervision et/ou du suivi du déploiement de l'agent Zabbix avec Scom, voici un management pack qui:

- Decouvre l'agent zabbix, sa version, ses propriétés "ZabbixPassiveServer" et "ZabbixActiveServer"

- Monitor le service ZabbixAgent

- propose deux console tasks:

       - Restart Zabbix Agent Service

       - Display Agent Configuration File (Chemin du fichier de config overridable)

NB: Les Discovery rules et Monitors sont désactivées par defaut.

 

ZabbixAgent.MP.xml (23,35 kb)

 

<?xml version="1.0" encoding="utf-8"?><ManagementPack ContentReadable="true" SchemaVersion="2.0" OriginalSchemaVersion="1.1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <Manifest>
    <Identity>
      <ID>ZabbixAgent.MP</ID>
      <Version>1.0.0.3</Version>
    </Identity>
    <Name>ZabbixAgent MP</Name>
    <References>
      <Reference Alias="SCInternal">
        <ID>Microsoft.SystemCenter.Internal</ID>
        <Version>7.0.8433.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Windows">
        <ID>Microsoft.Windows.Library</ID>
        <Version>7.5.8501.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Performance">
        <ID>System.Performance.Library</ID>
        <Version>7.0.8433.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="System">
        <ID>System.Library</ID>
        <Version>7.5.8501.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="SC">
        <ID>Microsoft.SystemCenter.Library</ID>
        <Version>7.0.8433.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Health">
        <ID>System.Health.Library</ID>
        <Version>7.0.8433.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
    </References>
  </Manifest>
  <TypeDefinitions>
    <EntityTypes>
      <ClassTypes>
        <ClassType ID="ZabbixAgent" Accessibility="Public" Abstract="false" Base="Windows!Microsoft.Windows.LocalApplication" Hosted="true" Singleton="false" Extension="false">
          <Property ID="Name" Type="string" AutoIncrement="false" Key="false" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" Scale="0" />
          <Property ID="Version" Type="string" AutoIncrement="false" Key="false" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" Scale="0" />
          <Property ID="ZabbixPassiveServer" Type="string" AutoIncrement="false" Key="false" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" Scale="0" />
          <Property ID="ZabbixActiveServer" Type="string" AutoIncrement="false" Key="false" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" Scale="0" />


        </ClassType>
        <ClassType ID="ZabbixAgent.MP.Application.Rollup" Accessibility="Public" Abstract="false" Base="System!System.Service" Hosted="false" Singleton="false" Extension="false">
          <Property ID="ApplicationName" Type="string" AutoIncrement="false" Key="true" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" Scale="0" />
        </ClassType>
      </ClassTypes>
      <RelationshipTypes>
        <RelationshipType ID="ZabbixAgent.MP.Application.Contains.ZabbixAgent" Accessibility="Public" Abstract="false" Base="System!System.Containment">
          <Source ID="Source" MinCardinality="0" MaxCardinality="2147483647" Type="ZabbixAgent.MP.Application.Rollup" />
          <Target ID="Target" MinCardinality="0" MaxCardinality="2147483647" Type="ZabbixAgent" />
        </RelationshipType>
      </RelationshipTypes>
    </EntityTypes>
	<ModuleTypes>
	
		<WriteActionModuleType ID="ZabbixAgent.DisplayAgentConfig.WA" Accessibility="Internal" Batching="false">
        <Configuration>
          <xsd:element minOccurs="1" name="ConfigFilePath" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="TimeoutSeconds" type="xsd:integer" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="ConfigFilePath" Selector="$Config/ConfigFilePath$" ParameterType="string" />
          <OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int" />
        </OverrideableParameters>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <WriteAction ID="PSWA" TypeID="Windows!Microsoft.Windows.PowerShellWriteAction">
                <ScriptName>ZabbixAgent.DisplayAgentConfig.WA.ps1</ScriptName>
                <ScriptBody>
#=================================================================================
#  Script to display Zabbix Agent Configuration File
#=================================================================================

param($ConfigFilePath)

#=================================================================================
# Constants section - modify stuff here:

# Assign script name variable for use in event logging
$ScriptName = "ZabbixAgent.DisplayAgentConfig.Task.ps1"
#=================================================================================


# Gather who the script is running as
$whoami = whoami


# Begin Main Script
#=================================================================================
Write-Host "Task Starting.  Running as $whoami"
#Load agent scripting object
Write-Host "Display Zabbix Agent Config File"
try
	{
	Get-Content -Path $ConfigFilePath
	}
	catch
	{
	write-host "Error during access to $ConfigFilePath file"
	}

#=================================================================================
                </ScriptBody>
                <Parameters>
                  <Parameter>
                    <Name>ConfigFilePath</Name>
                    <Value>$Config/ConfigFilePath$</Value>
                  </Parameter>
                </Parameters>
                <TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
              </WriteAction>
            </MemberModules>
            <Composition>
              <Node ID="PSWA" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.BaseData</OutputType>
        <InputType>System!System.BaseData</InputType>
      </WriteActionModuleType>
	
	</ModuleTypes>
  </TypeDefinitions>
  <Monitoring>
    <Discoveries>
      <Discovery ID="ZabbixAgent.Discovery" Enabled="false" Target="Windows!Microsoft.Windows.Computer" ConfirmDelivery="false" Remotable="true" Priority="Normal">
        <Category>Discovery</Category>
        <DiscoveryTypes>
          <DiscoveryClass TypeID="ZabbixAgent">
            <Property PropertyID="Name" />
            <Property TypeID="System!System.ConfigItem" PropertyID="ObjectStatus" />
            <Property TypeID="System!System.ConfigItem" PropertyID="AssetStatus" />
            <Property TypeID="System!System.ConfigItem" PropertyID="Notes" />
            <Property TypeID="System!System.Entity" PropertyID="DisplayName" />
          </DiscoveryClass>
        </DiscoveryTypes>
        <DataSource ID="DS" TypeID="Windows!Microsoft.Windows.WmiProviderWithClassSnapshotDataMapper">
          <NameSpace>\\$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$\root\cimv2</NameSpace>
          <Query>SELECT Name, DisplayName, PathName FROM Win32_Service WHERE Name like '%zabbix%'</Query>
          <Frequency>86400</Frequency>
          <ClassId>$MPElement[Name="ZabbixAgent"]$</ClassId>
          <InstanceSettings>
            <Settings>
              <Setting>
                <Name>$MPElement[Name="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Name>
                <Value>$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value>
              </Setting>
              <Setting>
                <Name>$MPElement[Name="ZabbixAgent"]/Name$</Name>
                <Value>$Data/Property[@Name='Name']$</Value>
              </Setting>
            </Settings>
          </InstanceSettings>
        </DataSource>
      </Discovery>
	     
	  
	 <Discovery ID="ZabbixAgent.Discovery.PowerShell.Properties.Discovery" Enabled="false" Target="ZabbixAgent" ConfirmDelivery="false" Remotable="true" Priority="Normal">
        <Category>Discovery</Category>
        <DiscoveryTypes>
          <DiscoveryClass TypeID="ZabbixAgent">
            <Property PropertyID="Version" />
            <Property PropertyID="ZabbixPassiveServer" />
            <Property PropertyID="ZabbixActiveServer" />
          </DiscoveryClass>
        </DiscoveryTypes>
        <DataSource ID="DS" TypeID="Windows!Microsoft.Windows.TimedPowerShell.DiscoveryProvider">
          <IntervalSeconds>86393</IntervalSeconds>
          <SyncTime />
          <ScriptName>ZabbixAgent.PowerShell.Properties.Discovery.ps1</ScriptName>
          <ScriptBody>
#=================================================================================
#  Script to gather additional properties of zabbix agent via PowerShell
#
#  Author: CJOURDAN
#  v1
#=================================================================================
param($SourceId,$ManagedEntityId,$ComputerName)


# Manual Testing section - put stuff here for manually testing script - typically parameters:
#=================================================================================
# $SourceId = '{00000000-0000-0000-0000-000000000000}'
# $ManagedEntityId = '{00000000-0000-0000-0000-000000000000}'
# $Computername = 'server.domain.com'
# $MGName = ''
# $IP = ''
#=================================================================================


# Constants section - modify stuff here:
#=================================================================================
# Assign script name variable for use in event logging
$ScriptName = "ZabbixAgent.PowerShell.Properties.Discovery.ps1"

#=================================================================================


# Starting Script section - All scripts get this
#=================================================================================
# Gather the start time of the script
$StartTime = Get-Date
#Set variable to be used in logging events
$whoami = whoami
# Load MOMScript API
$momapi = New-Object -comObject MOM.ScriptAPI
#Log script event that we are starting task
$momapi.LogScriptEvent($ScriptName,1006,0,"`nScript is starting.")
#=================================================================================


# Discovery Script section
#=================================================================================
# Load SCOM Discovery module
$DiscoveryData = $momapi.CreateDiscoveryData(0, $SourceId, $ManagedEntityId)
#=================================================================================


# Begin MAIN script section
#=================================================================================


# Get Infos from Zabbix Agent Configuration File
#=======================================================================			
$ZabbixConfFile = "C:\Program Files\zabbix_agents\conf\zabbix_agentd.win.conf"
#=======================================================================

try
{
$FileContent = Get-Content -Path $ZabbixConfFile -ErrorAction Stop
}
catch
{
$momapi.LogScriptEvent($ScriptName,1007,2,"`Error during retrieve of Zabbix Conf File Content")
exit 1
}


$ActiveServer =  $FileContent | Where-Object {$_ -like "ServerActive=*"}

$PassiveServer = $FileContent | Where-Object {$_ -like "Server=*"} 

If (!($ActiveServer) -or $ActiveServer.Length -eq 0)
	{
    #Write-Host "`Error during retrieve of Active Server data"
    $momapi.LogScriptEvent($ScriptName,1007,2,"`Error during retrieve of Active Server data or Active Server is not configured")
	$ActiveServer = "NULL"
	}
    Else
	{
	$ActiveServer = $ActiveServer.Replace('ServerActive=','')
	}


If (!($PassiveServer) -or $PassiveServer.Length -eq 0)
	{
    #write-host "`Error during retrieve of PassiveServer data"
    $momapi.LogScriptEvent($ScriptName,1007,2,"`Error during retrieve of PassiveServer data or Passive Server is not configured")
	$PassiveServer = "NULL"
	}
Else
	{
	$PassiveServer = $PassiveServer.Replace('Server=','')
	}


# Get Infos from Zabbix Agent exe (zabbix_agentd.exe)
#=======================================================================
try
	{
	$Version = $(Get-ChildItem -Path "C:\Program Files\zabbix_agents\bin\win64\zabbix_agentd.exe").VersionInfo.productversion
	}
catch
	{
	#write-host "`Error during retrieve of agent version"
    $momapi.LogScriptEvent($ScriptName,1007,2,"`Error during retrieve of agent version")
	$Version = "NULL"
	}



# Discovery Script section - Discovery scripts get this
#=================================================================================
$instance = $DiscoveryData.CreateClassInstance("$MPElement[Name='ZabbixAgent']$")
$instance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $Computername)
$instance.AddProperty("$MPElement[Name='ZabbixAgent']/Version$", $Version)
$instance.AddProperty("$MPElement[Name='ZabbixAgent']/ZabbixPassiveServer$", $PassiveServer)
$instance.AddProperty("$MPElement[Name='ZabbixAgent']/ZabbixActiveServer$", $ActiveServer)


$DiscoveryData.AddInstance($instance)

# Return Discovery Items Normally           
$DiscoveryData
# Return Discovery Bag to the command line for testing (does not work from ISE)
# $momapi.Return($DiscoveryData)
#=================================================================================


# End of script section
#=================================================================================
#Log an event for script ending and total execution time.
$EndTime = Get-Date
$ScriptTime = ($EndTime - $StartTime).TotalSeconds
$momapi.LogScriptEvent($ScriptName,1008,0,"`nScript has completed.") 
#=================================================================================
# End of script	  
		  </ScriptBody>
          <Parameters>
            <Parameter>
              <Name>SourceId</Name>
              <Value>$MPElement$</Value>
            </Parameter>
            <Parameter>
              <Name>ManagedEntityId</Name>
              <Value>$Target/Id$</Value>
            </Parameter>
            <Parameter>
              <Name>ComputerName</Name>
              <Value>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value>
            </Parameter>
            
          </Parameters>
          <TimeoutSeconds>600</TimeoutSeconds>
        </DataSource>
      </Discovery>
    </Discoveries>
   <Tasks>
	<Task ID="ZabbixAgent.RestartZabbixAgent.Task" Accessibility="Public" Enabled="true" Target="ZabbixAgent" Timeout="120" Remotable="true">
        <Category>Custom</Category>
        <WriteAction ID="WA" TypeID="Windows!Microsoft.Windows.ScriptWriteAction">
          <ScriptName>ZabbixAgent.RestartZabbixAgent.Task.vbs</ScriptName>
          <Arguments />
          <ScriptBody>
            Option Explicit
            On Error Resume Next
            Dim ScriptName, oAPI, objWMIService, oShell, oShellEnv, computerName, strCommand, objProcess, objProgram, strShell

            ScriptName = "ZabbixAgent.RestartZabbixAgent.Task.vbs"

            'Load momscript API
            Set oAPI = CreateObject("MOM.ScriptAPI")
            'Log script event that we are starting
            Call oAPI.LogScriptEvent(ScriptName, 1313, 2, "A command to restart the zabbix agent was sent.  We will attempt to stop and then restart the ZabbixAgent now.")

            'Begin Healthservice Restart
            Set oShell = WScript.CreateObject("WScript.Shell")
            set oShellEnv = oShell.Environment("Process")
            computerName = oShellEnv("ComputerName")
            'Echo that we are about to start for task output
            WScript.echo "Beginning Restart attempt for ZabbixAgent on " & computerName
            strCommand = "cmd /c net stop ZabbixAgent & cmd /c net start ZabbixAgent"
            Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
            Set objProcess = objWMIService.Get("Win32_Process")
            Set objProgram = objProcess.Methods_( _
            "Create").InParameters.SpawnInstance_
            objProgram.CommandLine = strCommand
            Set strShell = objWMIService.ExecMethod( _
            "Win32_Process", "Create", objProgram)
            'Echo that we are restarting for task output
            WScript.echo "Restarting ZabbixAgent on " & computerName
            'End ZabbixAgent Restart
          </ScriptBody>
          <TimeoutSeconds>60</TimeoutSeconds>
        </WriteAction>
      </Task>
	  
	  
	  <Task ID="ZabbixAgent.DisplayAgentConfig.Task" Accessibility="Public" Enabled="true" Target="ZabbixAgent" Timeout="120" Remotable="true">
        <Category>Custom</Category>
        <WriteAction ID="PSWA" TypeID="ZabbixAgent.DisplayAgentConfig.WA">
          <ConfigFilePath>C:\Program Files\zabbix_agents\conf\zabbix_agentd.win.conf</ConfigFilePath>
          <TimeoutSeconds>60</TimeoutSeconds>
        </WriteAction>

		
      </Task>
</Tasks>
	<Monitors>
      <UnitMonitor ID="ZabbixAgent.ZabbixAgentService.Monitor" Accessibility="Public" Enabled="false" Target="ZabbixAgent" ParentMonitorID="Health!System.Health.AvailabilityState" Remotable="true" Priority="Normal" TypeID="Windows!Microsoft.Windows.CheckNTServiceStateMonitorType" ConfirmDelivery="false">
        <Category>Custom</Category>
        <OperationalStates>
          <OperationalState ID="ZabbixAgent.ZabbixAgentService.Monitor.OK" MonitorTypeStateID="Running" HealthState="Success" />
          <OperationalState ID="ZabbixAgent.ZabbixAgentService.Monitor.KO" MonitorTypeStateID="NotRunning" HealthState="Error" />
        </OperationalStates>
        <Configuration>
          <ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</ComputerName>
          <ServiceName>ZabbixAgent</ServiceName>
          <CheckStartupType>true</CheckStartupType>
        </Configuration>
      </UnitMonitor>
    </Monitors>

  

  </Monitoring>
 
  <LanguagePacks>
    <LanguagePack ID="FRA" IsDefault="true">
      <DisplayStrings>
        <DisplayString ElementID="ZabbixAgent.MP">
          <Name>ZabbixAgent MP</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.MP.Application.Contains.ZabbixAgent">
          <Name>ZabbixAgent MP Application Contains ZabbixAgent</Name>
          <Description>Defines a System.Containment relationship between ZabbixAgent.MP.Application.Rollup and ZabbixAgent.</Description>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.MP.Application.Rollup">
          <Name>ZabbixAgent MP Application Rollup</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.MP.Application.Rollup" SubElementID="ApplicationName">
          <Name>Application Name</Name>
          <Description>Application Name</Description>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent">
          <Name>ZabbixAgent</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.Discovery">
          <Name>ZabbixAgent Discovery</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.Discovery.PowerShell.Properties.Discovery">
          <Name>ZabbixAgent PowerShell Properties Discovery</Name>
        </DisplayString>

        <DisplayString ElementID="ZabbixAgent" SubElementID="Name">
          <Name>Name</Name>
        </DisplayString>
		<DisplayString ElementID="ZabbixAgent" SubElementID="Version">
          <Name>Version</Name>
        </DisplayString>
		<DisplayString ElementID="ZabbixAgent" SubElementID="ZabbixPassiveServer">
          <Name>ZabbixPassiveServer</Name>
        </DisplayString>
		<DisplayString ElementID="ZabbixAgent" SubElementID="ZabbixActiveServer">
          <Name>ZabbixActiveServer</Name>
        </DisplayString>
		<DisplayString ElementID="ZabbixAgent.ZabbixAgentService.Monitor">
          <Name>Zabbix Agent Service</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.ZabbixAgentService.Monitor" SubElementID="ZabbixAgent.ZabbixAgentService.Monitor.OK">
          <Name>Service is running</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.ZabbixAgentService.Monitor" SubElementID="ZabbixAgent.ZabbixAgentService.Monitor.KO">
          <Name>Service is not running</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.RestartZabbixAgent.Task">
          <Name>Restart Zabbix Agent Service</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.DisplayAgentConfig.Task">
          <Name>Display Agent Configuration File</Name>
        </DisplayString>


      </DisplayStrings>

    </LanguagePack>
  
  <LanguagePack ID="ENU" IsDefault="false">
      <DisplayStrings>
        <DisplayString ElementID="ZabbixAgent.MP">
          <Name>ZabbixAgent MP</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.MP.Application.Contains.ZabbixAgent">
          <Name>ZabbixAgent MP Application Contains ZabbixAgent</Name>
          <Description>Defines a System.Containment relationship between ZabbixAgent.MP.Application.Rollup and ZabbixAgent.</Description>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.MP.Application.Rollup">
          <Name>ZabbixAgent MP Application Rollup</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.MP.Application.Rollup" SubElementID="ApplicationName">
          <Name>Application Name</Name>
          <Description>Application Name</Description>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent">
          <Name>ZabbixAgent</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.Discovery">
          <Name>ZabbixAgent Server Discovery</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.Discovery.PowerShell.Properties.Discovery">
          <Name>ZabbixAgent PowerShell Properties Discovery</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent" SubElementID="Name">
          <Name>Name</Name>
        </DisplayString>
		<DisplayString ElementID="ZabbixAgent" SubElementID="Version">
          <Name>Version</Name>
        </DisplayString>
		<DisplayString ElementID="ZabbixAgent" SubElementID="ZabbixPassiveServer">
          <Name>ZabbixPassiveServer</Name>
        </DisplayString>
		<DisplayString ElementID="ZabbixAgent" SubElementID="ZabbixActiveServer">
          <Name>ZabbixActiveServer</Name>
        </DisplayString>
		<DisplayString ElementID="ZabbixAgent.ZabbixAgentService.Monitor">
          <Name>Zabbix Agent Service</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.ZabbixAgentService.Monitor" SubElementID="ZabbixAgent.ZabbixAgentService.Monitor.OK">
          <Name>Service is running</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.ZabbixAgentService.Monitor" SubElementID="ZabbixAgent.ZabbixAgentService.Monitor.KO">
          <Name>Service is not running</Name>
        </DisplayString>
        <DisplayString ElementID="ZabbixAgent.RestartZabbixAgent.Task">
          <Name>Restart Zabbix Agent Service</Name>
        </DisplayString>
	    <DisplayString ElementID="ZabbixAgent.DisplayAgentConfig.Task">
          <Name>Display Agent Configuration File</Name>
        </DisplayString>


      </DisplayStrings>
    </LanguagePack>
  </LanguagePacks>
</ManagementPack>


 

 

 

 

SCOM - Script - Fonction de suppression d'agent a distance

La fonction ci-dessous permet de supprimer un agent scom en se connectant a distance a un management server donné.

Function Remove-SCOMAgent
{

 [CmdletBinding()]
 Param
    (
        [Parameter(Mandatory=$true, Position=0)]
        [string]$MServer,
        [Parameter(Mandatory=$true, Position=1)]
        [string]$AgentName,
        [Parameter(Mandatory=$true, Position=2)]
        [string]$User,
        [Parameter(Mandatory=$true, Position=3)]
        [string]$Domain

    )

$Cred = Get-Credential -Message "password" -Username "$Domain\$User"
	


#Import-Module OperationsManager            
New-SCOMManagementGroupConnection -ComputerName $MServer -Credential $Cred
Start-Sleep -s 3

$administration = (Get-SCOMManagementGroup).GetAdministration();
Start-Sleep -Milliseconds 500
$agentManagedComputerType = [Microsoft.EnterpriseManagement.Administration.AgentManagedComputer];
$genericListType = [System.Collections.Generic.List``1]
$genericList = $genericListType.MakeGenericType($agentManagedComputerType)
$agentList = new-object $genericList.FullName
$agent = Get-SCOMAgent *$AgentName*

If(!($agent))
{
$message = "No agent found with name `"$AgentName`""
$message
exit
}

Start-Sleep -S 5
$agentList.Add($agent);

$genericReadOnlyCollectionType = [System.Collections.ObjectModel.ReadOnlyCollection``1]
$genericReadOnlyCollection = $genericReadOnlyCollectionType.MakeGenericType($agentManagedComputerType)
$agentReadOnlyCollection = new-object $genericReadOnlyCollection.FullName @(,$agentList);    
$administration.DeleteAgentManagedComputers($agentReadOnlyCollection);
}

Remove-SCOMAgent -MServer MyMS -AgentName serv1 -User Myaccount -Domain MyDomain



 

Supervision - Zabbix - Script - Utilisation des Regex pour rechercher des données numeriques dans une chaine de caractère

Le cas présenté ici, peut être indépendant de l'outil de monitoring. Il s'agit de devoir alerter et donc définir des seuil sur une donnée qui est présenté par défaut sous forme de texte.

Pour être un peu plus clair, dans le contexte, un équipement snmp renvoi l'information d'utilisation de son file system sous la forme suivante:

"/tmp=0, /var=26, /var/log=0, /=22"

il s'agit en effet de la valeur de l'OID atpDiskUsage dans la MIB ATP-SNMP-MIB (Symantec Advanced Threat Protection)

Pour pouvoir traiter les valeurs d'utilisation du file system comme des nombre, les expressions régulières sont d'un grand secours.

Supposons que l'on veuille alerter sur le fait que "/var" soit au dessus de 80.

Dans ce cas l'expression proposé est la suivante régulière sera la suivante:

^.*(\/var=)[8-9][0-9]|100,.*$

Explication --> ^ : début de chaine

                      .*(\/var=) : n caractère n fois, suivi de "/var="  (on doit échapper le caractère '/' avec '\')

                      [8-9][0-9] : le range de chiffre est de 80 a 99

                      |100 : ou bien sur 100.

                       ,.* : la virgule présente, suivi de n caractère n fois

                       $: fin de chaine

Ce qui, pour nos 4 points de montage du file system donnera:

^.*(\/var=)[8-9][0-9]|100,.*$

^.*(\/tmp=)[8-9][0-9]|100,.*$

^.*(\/var\/log=)[8-9][0-9]|100,.*$

^.*(\/=)[8-9][0-9]|100.*$

Dans le contexte de Zabbix, Les expressions régulières ci-dessus ont donc été intégrées chacune dans un trigger utilisant la fonction "regexp() - Regular expression matching last value in period (1- match, 0 - not match)".

Indépendamment de l'outil de supervision, n'hésitez pas a user et abuser d'un outil de construction de regex tel que https://regex101.com/

 

SCOM - SCRIPT - Fonction powershell pour lister toutes les instances d'une machine

Le script ci-dessous intègre la requête SQL de récupération des instances d'une machine, sous forme de fonction.

All_InstancesForOneAgent_vSQLQuery.ps1

 

# SCRIPT THAT QUERY SCOM DATABASE TO GET ALL INSTANCES OF ALL CLASSES FOR A GIVEN COMPUTER ($TargetAgent)
# $TargetComputer must be Short name of computer because we look for this specific string in name, displayname and path of instances.

param(
#Short name of computer
$TargetComputer = "MyComputer"
)


# Function  Invoke-InstancesFromSQL

Function Invoke-InstancesFromSQL
                            {
                                param(
                                    [string]$dataSource = "MyScomSQLServer\OPSMGR",
                                    [string]$database = "OperationsManager",
                                    [string]$TargetComputer,
                                    [string]$sqlCommand = 
                                            $("Use $Database
                                                SELECT 
                                                   MTV.DisplayName as ClassName
	                                               ,MEGV.Path as Instance_Path
	                                               ,MEGV.Id as Instance_Id
	                                               ,MEGV.[DisplayName] as 'Entity_DisplayName'
	                                               ,MEGV.[Name] as 'Entity_Name'
	                                               ,MEGV.[FullName] as Entity_FullName
                                                   ,[IsManaged]
                                                   ,[IsDeleted]
                                                   ,HealthState = 
													CASE WHEN InMaintenanceMode = '0'
														  THEN 
															CASE [HealthState]
															WHEN '0' THEN 'Not Monitored'
															WHEN '1' THEN 'OK'
															WHEN '2' THEN 'Warning'
															WHEN '3' THEN 'Critical'
															END
														WHEN InMaintenanceMode = '1'
														THEN 
															CASE [HealthState]
															WHEN '0' THEN 'In Maintenance Mode'
															WHEN '1' THEN 'OK'
															WHEN '2' THEN 'Warning'
															WHEN '3' THEN 'Critical'
															END
													END
                                                  ,Is_Available = CASE [IsAvailable]
			                                            WHEN '1' THEN 'YES'
			                                            WHEN '2' THEN 'NO'
			                                            END
                                                  
                                                  ,In_MaintenanceMode = CASE [InMaintenanceMode]
			                                            WHEN '0' THEN 'NO'
			                                            WHEN '1' THEN 'YES'
			                                            END
                                                  
                                                  ,Start_Of_Maintenance = CASE WHEN InMaintenanceMode = '0' 
			                                            THEN null
			                                            ELSE MMV.StartTime
			                                            END
	                                              ,End_Of_Maintenance = CASE WHEN InMaintenanceMode = '0'
			                                            THEN null
			                                            ELSE MMV.ScheduledEndTime
			                                            END
                                                  	                                              
                                                  ,Maintenance_RootCause = 
														CASE WHEN InMaintenanceMode = '0'
														  THEN null
															ELSE 
																CASE MMV.ReasonCode
																WHEN '0' THEN 'Other (Planned)'
																WHEN '1' THEN 'Other (Unplanned)'
																  WHEN '2' THEN 'Hardware: Maintenance (Planned)'
																  WHEN '3' THEN 'Hardware: Maintenance (Unplanned)'
																  WHEN '4' THEN 'Hardware: Installation (Planned)'
																  WHEN '5' THEN 'Hardware: Installation (Unplanned)'
																  WHEN '6' THEN 'Operating System: Reconfiguration (Planned)'
																  WHEN '7' THEN 'Operating System: Reconfiguration (Unplanned)'
																  WHEN '8' THEN 'Application: Maintenance (Planned)'
																  WHEN '9' THEN 'Application: Maintenance (Unplanned)'
																  WHEN '10' THEN 'Application: Installation (Planned)'
																  WHEN '11' THEN 'Application: Unresponsive'
																  WHEN '12' THEN 'Application:  Unstable'
																  WHEN '13' THEN 'Security Issue'
																  WHEN '14' THEN 'Loss of network connectivity (Unplanned)'
																END
															END
                                                  
		                                            ,Maintenance_Reason =   
														CASE WHEN InMaintenanceMode = '0' 
														    THEN null
															    ELSE MMV.Comments
														END
	  
      
                                              FROM [OperationsManager].[dbo].[ManagedEntityGenericView] MEGV

                                              INNER JOIN [dbo].[ManagedTypeView] MTV on MEGV.MonitoringClassId = MTV.Id
                                              INNER JOIN [OperationsManager].[dbo].[MaintenanceModeView] MMV on MEGV.id = MMV.BaseManagedEntityId
                                              WHERE (MEGV.Name  like '%$TargetComputer%' OR MEGV.DisplayName  like '%$TargetComputer%' OR MEGV.Path  like '%$TargetComputer%')
                                              and MTV.LanguageCode = 'ENU'
                                              and MEGV.HealthState is not null
                                              and MEGV.IsDeleted <> '1'
                                              ORDER BY MTV.DisplayName
                                            ")
                                           )


                                    $connectionString = "Data Source=$dataSource; " +
                                    "Integrated Security=SSPI; " +
                                    "Initial Catalog=$database"

                                $connection = new-object system.data.SqlClient.SQLConnection($connectionString)
                                $command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)
                                
                                try
                                {
                                $connection.Open()
                                }
                                catch
                                {
                                write-host -F Red $("Error during sql connection - check the credentials used").ToUpper()
                                exit 1
                                }

                                $adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
                                $dataset = New-Object System.Data.DataSet
                                $adapter.Fill($dataSet) | Out-Null

                                $connection.Close()
                                $dataSet.Tables

                              }


[array]$table = Invoke-InstancesFromSQL -TargetComputer $TargetComputer


write-host "`nCOMPUTER: $TargetComputer"

Write-Host "`nNb Of Objects:"$table.count""

$table | ft -Property ClassName,Instance_Path,Entity_DisplayName,Entity_Name,Entity_FullName,HealthState,Is_Available,In_MaintenanceMode,Start_Of_Maintenance,End_Of_Maintenance,Maintenance_RootCause,Maintenance_Reason



# TO FILTER ON SPECIFIC CLASS
# $table | Where-Object {$_.CLASS_NAME -in ('Windows computer','Health Service Watcher','VMware vSphere Host','VMWare Virtual Machine','HPE ProLiant Server')} | ft -AutoSize



# SIMULATE START OF MAINTENANCE MODE FOR THE INSTANCES
#$table | foreach {Get-SCOMClassInstance -id $_.instance_id} | foreach {start-SCOMMaintenanceMode -instance $_ -WhatIf -EndTime $((Get-Date).AddHours(1))}

 

 

 

 

 

 

Script Powershell pour Zabbix - Gerer les items d'un host

L'exemple ci-dessous utilise le module PowerShell PSBBIX qui encapsule les commandes de l'API Zabbix.

Parmi les nombreuses commandes, pour exemple, le script propose de désactiver ou activer les items (points de supervision) d'un host spécifique.

N'hésitez pas pour plus de détails a aller voir le github de PSBBIX (https://github.com/yubu/psbbix-zabbix-api)

ZabbixManageHostItems.ps1

#########################################################
### ENABLE/DISABLED ALL SPECIFIC ITEMS FOR A ZABBIX HOST
### Params:
### $ZabbixSrv: Target Zabbix Server
### $TargetHost: Target host to treat
### $ItemPattern: Pattern of Items to check
### $Action: Disable or Enable
#########################################################


Param(
[Parameter(Mandatory=$true)] $ZabbixSrv,
[Parameter(Mandatory=$true)] $TargetHost,
[Parameter(Mandatory=$true)] $ItemPattern,
[Parameter(Mandatory=$true)] $Action
)


if ($PSBoundParameters.Count -lt 4)
    {
    write-host -F Red "Too few arguments!"
    write-host -F Yellow "ZabbixSrv: Target Zabbix Server`nTargetHost: Target host to treat`nItemPattern: Pattern of Items to check`nAction: Disable or Enable"
    exit 1
    } 

switch($Action)
{
"disable" {$status = 1}
"enable" {$status = 0}
default {Write-Host -F Red "Possible value for Action is 'enable' or 'disable' - END OF SCRIPT" ; exit 0}
}



# Check if psbbix module is loaded
if (!(get-module psbbix))
    {
    write-host -F Yellow "psbbix module is not loaded...search module to load it..."
    $modulepath = $env:PSModulePath -split ‘;’ | foreach {Get-ChildItem -Recurse -Path $_ | Where-Object {$_.name -eq "psbbix.psm1"}}
    if (!$modulepath)
        {
        write-host -F Yellow "unable to find psbbix.psm1...get it on https://github.com/yubu/psbbix-zabbix-api"
        exit 1
        }
    Else
        {
            try
            {
            Import-Module $($modulepath | select -Unique).fullname
            }
            catch
            {
            write-host -F error "Error during import of psbbix module"
            exit 1
            }
        }
    Write-Host -F Green "...Module loaded"

    }


$cred = Get-Credential -Credential "myaccount"


# Connect to zabbix server
try
{
Connect-Zabbix $ZabbixSrv -PSCredential $cred
}
catch
{
Write-Host -F Red "Error during connection to $ZabbixSrv"
exit 1
}


# Get all items that we want to disable
$items = Get-ZabbixItem -hostid $(Get-ZabbixHost -HostName $TargetHost).hostid | Where-Object {$_.name -like $ItemPattern}

if ($items.Count -eq 0)
    {
    Write-Host -F Yellow "No items found with '$ItemPattern' pattern for $TargetHost host"
    }

Else
    {
        try
        {
        $items | foreach {Set-ZabbixItem -itemid $_.itemid -status $status}
        }
        catch
        {
        write-host -F Red "Error during modification of Items status"
        exit 1
        }

    }


Write-host "`nFollowing items have been treated for $TargetHost`:`n"
$items = Get-ZabbixItem -hostid $(Get-ZabbixHost -HostName $TargetHost).hostid | Where-Object {$_.name -like $ItemPattern}
$items | foreach {$_.name +" -- "+  $(switch($_.status){0{"enabled"}1{"disabled"}})}


 

Script Powershell - Archive log files to Zip

Le script ci-dessous archive des fichiers de log plus ancien que $daysthreshold vers une archive zip existante ($zipfilepath). Il crée le sous dossier et l'archive zip horodatée si elle n'existe pas.

ArchiveLogToZip.ps1

 

###############################################################
### ArchiveLogs.ps1                                    ###
### Add Log Files older than $days to existing zip archive. ###

### Params
### $logpath: Log Folder
### $archpath: Archive Folder
### $zipfilePath: zip file path
### $daysthreshold: Treat log older than $daysthreshold days
###############################################################
 
Param(
$logpath = "C:\MyLogFolder", 
$archpath = "C:\MyLogFolder\Archive\",
$zipfilePath =  "$archpath"+"*.zip",
[int]$daysthreshold = 0 
)
 



# Test if $archpath exist
If ( -not (Test-Path $archpath)) {New-Item $archpath -type directory} 
 
# Get items to archive
$ItemsToArc = Get-Childitem -Path $logpath -recurse | Where-Object {$_.extension -eq ".log" -and $_.LastWriteTime -lt (get-date).AddDays(-$daysthreshold)}

# Log and exit if  No items to archive
If (! $ItemsToArc)
    {
    Write-Host -F Yellow "No items to archive - Check the existence of the logs"
    exit 0
    }



# If the zip file not exist, create it
if (!(Get-Item $zipfile -ErrorAction SilentlyContinue))
{
$date = $(Get-Date).ToString("MM-dd-yyyy_HH-mm-ss")
New-Item -Path "$archpath$date.zip"
$zipfile = $(Get-Item "$archpath$date.zip").FullName
}
Else
{
$zipfile = $(Get-Item $zipfilePath).FullName
}


# Create a com object that will represent the zip file
$Zip = New-Object -ComObject Shell.Application

write-progress -activity "Archiving Data" -status "Progress..." 

try
{
$ItemsToArc | foreach {$Zip.namespace($zipfile).Movehere($_.fullname,8) ; start-sleep -Seconds 3}
}
catch
{
Write-Host "Error during File add to Zip"
}

 

Script Powershell - Fonction de test de ports reseaux

Ci-dessous une fonction dont le besoin est récurrent, pour tester la disponibilité d'un ou plusieurs ports réseaux sur une ou plusieurs machines.

 test-port.ps1 (10,05 kb)

# TEST-PORT
<#
.SYNOPSIS
         CHECK AVAILABILITY OF NETWORK PORT CONNECTION ON REMOTE COMPUTERS
.OUTPUTS 
         Return Open Status and details
.PARAMETER 
        $computer: One or more target computers
        $port: One or more port to test
        $TCPtimeout: Timeout for TCP, in ms
        $UDPtimeout: Timeout for UDP, in ms
        $TCP: Precise TCP connection
        $UDP: Precise UDP connection
                 

.USAGE:
#Test-Port -computer (get-content .\servers.txt) -port 3389
#Test-Port -computer (get-content .\servers.txt) -port 80,443,23000,17990 -TCP -TCPtimeout 1000
#Test-Port -computer myserver -port 8080,8443,10443,3389,443,80,22 -TCP -UDP
#>



function Test-Port{  




 
[cmdletbinding(  
    DefaultParameterSetName = '',  
    ConfirmImpact = 'low'  
)]  
    Param(  
        [Parameter(  
            Mandatory = $True,  
            Position = 0,  
            ParameterSetName = '',  
            ValueFromPipeline = $True)]  
            [array]$computer,  
        [Parameter(  
            Position = 1,  
            Mandatory = $True,  
            ParameterSetName = '')]  
            [array]$port,  
        [Parameter(  
            Mandatory = $False,  
            ParameterSetName = '')]  
            [int]$TCPtimeout=500,  
        [Parameter(  
            Mandatory = $False,  
            ParameterSetName = '')]  
            [int]$UDPtimeout=500,             
        [Parameter(  
            Mandatory = $False,  
            ParameterSetName = '')]  
            [switch]$TCP,  
        [Parameter(  
            Mandatory = $False,  
            ParameterSetName = '')]  
            [switch]$UDP                                    
        )  
    Begin {  
        If (!$tcp -AND !$udp) {$tcp = $True}  
        
        $ErrorActionPreference = "SilentlyContinue"  
        $report = @()  
    }  
    Process {     
        ForEach ($c in $computer) {  
            ForEach ($p in $port) {  
                If ($tcp) {    
                    #Create temporary holder   
                    $temp = "" | Select hostname,Server, Port, TypePort, Open, Notes  
                    #Create object for connecting to port on computer  
                    $tcpobject = new-Object system.Net.Sockets.TcpClient  
                    #Connect to remote machine's port                
                    $connect = $tcpobject.BeginConnect($c,$p,$null,$null)  
                    #Configure a timeout before quitting  
                    $wait = $connect.AsyncWaitHandle.WaitOne($TCPtimeout,$false)  
                    #If timeout  
                    If(!$wait) {  
                        #Close connection  
                        $tcpobject.Close()  
                        Write-Verbose "Connection Timeout"  
                        #Build report  
                        $temp.hostname= [System.Net.dns]::Resolve($c).hostname
                        $temp.Server = $c  
                        $temp.Port = $p  
                        $temp.TypePort = "TCP"  
                        $temp.Open = "False"  
                        $temp.Notes = "Connection to Port Timed Out"  
                    } Else {  
                        $error.Clear()  
                        $tcpobject.EndConnect($connect) | out-Null  
                        #If error  
                        If($error[0]){  
                            #Begin making error more readable in report  
                            [string]$string = ($error[0].exception).message  
                            $message = (($string.split(":")[1]).replace('"',"")).TrimStart()  
                            $failed = $true  
                        }  
                        #Close connection      
                        $tcpobject.Close()  
                        #If unable to query port to due failure  
                        If($failed){  
                            #Build report 
                            $temp.hostname= [System.Net.dns]::Resolve($c).hostname 
                            $temp.Server = $c  
                            $temp.Port = $p  
                            $temp.TypePort = "TCP"  
                            $temp.Open = "False"  
                            $temp.Notes = "$message"  
                        } Else{  
                            #Build report
                            $temp.hostname= [System.Net.dns]::Resolve($c).hostname  
                            $temp.Server = $c  
                            $temp.Port = $p  
                            $temp.TypePort = "TCP"  
                            $temp.Open = "True"    
                            $temp.Notes = ""  
                        }  
                    }     
                    #Reset failed value  
                    $failed = $Null      
                    #Merge temp array with report              
                    $report += $temp  
                }      
                If ($udp) {  
                    #Create temporary holder   
                    $temp = "" | Select Server, Port, TypePort, Open, Notes                                     
                    #Create object for connecting to port on computer  
                    $udpobject = new-Object system.Net.Sockets.Udpclient
                    #Set a timeout on receiving message 
                    $udpobject.client.ReceiveTimeout = $UDPTimeout 
                    #Connect to remote machine's port                
                    Write-Verbose "Making UDP connection to remote server" 
                    $udpobject.Connect("$c",$p) 
                    #Sends a message to the host to which you have connected. 
                    Write-Verbose "Sending message to remote host" 
                    $a = new-object system.text.asciiencoding 
                    $byte = $a.GetBytes("$(Get-Date)") 
                    [void]$udpobject.Send($byte,$byte.length) 
                    #IPEndPoint object will allow us to read datagrams sent from any source.  
                    Write-Verbose "Creating remote endpoint" 
                    $remoteendpoint = New-Object system.net.ipendpoint([system.net.ipaddress]::Any,0) 
                    Try { 
                        #Blocks until a message returns on this socket from a remote host. 
                        Write-Verbose "Waiting for message return" 
                        $receivebytes = $udpobject.Receive([ref]$remoteendpoint) 
                        [string]$returndata = $a.GetString($receivebytes)
                        If ($returndata) {
                           Write-Verbose "Connection Successful"  
                            #Build report
                            $temp.hostname= [System.Net.dns]::Resolve($c).hostname  
                            $temp.Server = $c  
                            $temp.Port = $p  
                            $temp.TypePort = "UDP"  
                            $temp.Open = "True"  
                            $temp.Notes = $returndata   
                            $udpobject.close()   
                        }                       
                    } Catch { 
                        If ($Error[0].ToString() -match "\bRespond after a period of time\b") { 
                            #Close connection  
                            $udpobject.Close()  
                            #Make sure that the host is online and not a false positive that it is open 
                            If (Test-Connection -comp $c -count 1 -quiet) { 
                                Write-Verbose "Connection Open"  
                                #Build report
                                $temp.hostname= [System.Net.dns]::Resolve($c).hostname  
                                $temp.Server = $c  
                                $temp.Port = $p  
                                $temp.TypePort = "UDP"  
                                $temp.Open = "True"  
                                $temp.Notes = "" 
                            } Else { 
                                <# 
                                It is possible that the host is not online or that the host is online,  
                                but ICMP is blocked by a firewall and this port is actually open. 
                                #> 
                                Write-Verbose "Host maybe unavailable"  
                                #Build report
                                $temp.hostname= [System.Net.dns]::Resolve($c).hostname  
                                $temp.Server = $c  
                                $temp.Port = $p  
                                $temp.TypePort = "UDP"  
                                $temp.Open = "False"  
                                $temp.Notes = "Unable to verify if port is open or if host is unavailable."                                 
                            }                         
                        } ElseIf ($Error[0].ToString() -match "forcibly closed by the remote host" ) { 
                            #Close connection  
                            $udpobject.Close()  
                            Write-Verbose "Connection Timeout"  
                            #Build report 
                            $temp.hostname= [System.Net.dns]::Resolve($c).hostname 
                            $temp.Server = $c  
                            $temp.Port = $p  
                            $temp.TypePort = "UDP"  
                            $temp.Open = "False"  
                            $temp.Notes = "Connection to Port Timed Out"                         
                        } Else {                      
                            $udpobject.close() 
                        } 
                    }     
                    #Merge temp array with report              
                    $report += $temp 
					$temp
                }                                  
            }  
        }                  
    }  
    End {  
        #Generate Report  
        $report |ft -AutoSize 
    }
}





 

SCOM - Script de Fermeture des alertes liées a des monitors en état Healthy

Ci-dessous une nouvelle version d'un script de fermeture des alertes liées a des monitors en état Healthy. En effet meme si le cas contraire est plus fréquent (alerte fermée alors que le monitor est encore en état Warning ou Critical), il se peut que l'on doivent fermer les alertes de monitors en état Healthy.

Le script affiche clairement la sortie des alertes a traiter et log cette sortie dans l'eventlog.

 

# SCRIPT TO CHECK INCONSISTENCY BETWEEN NOT CLOSED ALERTS AND HEALTHY MONITORS 


Param(
# Treat alerts that has been modified since less than $LastModifHours
$LastModifHours = 2
)

$ScriptName = "CloseAlertsFromHealthyMonitors.ps1"


# FUNCTIONS

# Check if a source with script name exist in operationsmanager eventlog to log some specific events 
         Function NewEventSource 
         { 
         if(!(Test-Path "HKLM:\SYSTEM\CurrentControlSet\services\eventlog\Operations Manager\$ScriptName")) 
         { 
         New-EventLog -LogName "Operations Manager" -Source $ScriptName 
         }
         } 


# END FUNCTIONS



#Log of script execution 
NewEventSource 
write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1000 -Message "Execution of script $ScriptName (Value of LastModifHours is $LastModifHours hours)" -EntryType Information

# Import of Scom Module
Import-Module OperationsManager


# Get list of closed alerts with following criterias:
# - Not Closed
# - Generated by a monitor

$NotClosedAlerts = Get-SCOMAlert -ResolutionState (0..254)  | where { ($_.ismonitoralert -eq $true) -and $_.LastModified -gt (Get-Date).addhours(-$LastModifHours)}


# Variable to store the result of alert treatment.
# Header
$Result = "`n*********** CHECK INCONSISTENCY BETWEEN NOT CLOSED ALERTS AND HEALTHY MONITORS ***********"

$Result += "`n START `n"


for ($i=0;$i -le $NotClosedAlerts.GetUpperBound(0);$i=$i+1) 
{
# Display alert Nb
$NotClosedAlert = $NotClosedAlerts[$i]
$Result +=  "`n`nalert $i ------------------------------"



# Get IDs from Closed alert 
$mrid = $NotClosedAlert.monitoringruleid 
$mcid = $NotClosedAlert.monitoringclassid 
$moid = $NotClosedAlert.monitoringobjectid 



# Get corresponding class 
$monitoringclass = Get-SCOMClass -id $mcid

# Get the corresponding instance with following criterias:
# - HealthState equal Success 
$MyInstance = Get-SCOMMonitoringObject -Class $monitoringclass | where {$_.id -eq $moid -and $_.HealthState -eq "Success"} 

# If there is no instances no need to reset (exit the loop and treat the next closed alert)
If(!($MyInstance))
{
$Result += "No Instance found in Success state for the alert `"$($NotClosedAlert.Name)`" - NO NEED TO CLOSE ALERT"
}
Else
{
$Result += "`nThe following alert must be closed: `n"
$Result += "NAME: $($NotClosedAlert.Name)`n"
$Result += "ID: $($NotClosedAlert.Id)`n"
$Result += "COMPUTER OR OBJECT: $($NotClosedAlert.MonitoringObjectDisplayName)`n"
$Result += "COMPUTER OR OBJECT FULL PATH: $($NotClosedAlert.MonitoringObjectFullName)`n"
$Result += "COMPUTER OR OBJECT HEALTH STATE: $($NotClosedAlert.MonitoringObjectHealthState)`n"
$Result += "TIME RAISED: $($NotClosedAlert.TimeRaised)`n"
$Result += "TIME LAST MODIFIED: $($NotClosedAlert.LastModified)`n"



    try
    {
    Set-SCOMAlert -Alert $NotClosedAlert -ResolutionState 255
    $Result += "Closing of alert `"$($NotClosedAlert.Name)`"..."
    $Result += "-------------------------------------------------------`n`n`n"
    # Update of Alert History Text
    $NotClosedAlert.Update("Alert closed by $ScriptName script")
    }
    catch
    {
    $Result += "Error during the close of alert `"$($NotClosedAlert.Name)`" (ALERT ID: $($NotClosedAlert.Id))"
    }
}

}

$Result += "`n`n END `n"

# Check if $Result contains error of alert closing
if ($($Result | Out-String).Contains("Error during the close of alert"))
{
$Result += "At least one Error has been encountered during closing of some alerts"
NewEventSource 
write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1001 -Message $Result -EntryType Warning
}
Else
{
$Result += "`n OK - Treatment of Alerts has ending without Error"
NewEventSource 
write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1002 -Message $Result -EntryType Information

}

# Display Result
$Result

 

 

Zabbix API with Powershell – Example

L'API de Zabbix, basée sur le standard JSON-RPC 2.0 peux bien sur etre intérrogée aussi avec Powershell.

 Ci-dessous un script montrant le principe d'interrogation de l'API, en recuperant certaines infos.

 Vous devez renseigner un compte (<my_zabbix_account>) avec au minimum les droits de lecture sur Zabbix, et le nom ou l'ip du serveur Front Web (<zabbix_frontweb_server>).

 

### Query Zabbix Through native zabbix json api

    $credential = Get-Credential -Credential "my_zabbix_account"

$baseurl = 'https://<name_or_ip_of_front_server>/zabbix'
$params = @{
    body =  @{
        "jsonrpc"= "2.0"
        "method"= "user.login"
        "params"= @{
            "user"= $credential.UserName
            "password"= $credential.GetNetworkCredential().Password
        }
        "id"= 1
        "auth"= $null
    } | ConvertTo-Json
    uri = "$baseurl/api_jsonrpc.php"
    headers = @{"Content-Type" = "application/json"}
    method = "Post"
}

[System.Net.ServicePointManager]::SecurityProtocol = 'tls12'
[Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

$result = Invoke-WebRequest @params -UseBasicParsing



$params.body = @{
    "jsonrpc"= "2.0"
    "method"= "host.get"
    "params"= @{
        output = "extend"
		selectFunctions = "extend"
		selectLastEvent = "extend"
		selectGroups = "extend"
		selectHosts = "extend"
    }
    auth = ($result.Content | ConvertFrom-Json).result
    id = 2
} | ConvertTo-Json

$result = Invoke-WebRequest @params -UseBasicParsing
$result = $result.Content | ConvertFrom-Json