PI Services

Le blog des collaborateurs de PI Services

SCOM 2012 : créer un grand nombre de règles en quelques minutes

Lors de la création d’un nouveau Management Pack pour une application métier, il arrive qu’un grand nombre de règles ou de moniteurs similaires (alerte sur événement windows, collecte de compteur de performance…) doivent être ajoutées.

Il est bien sûr toujours possible de les créer les une après les autres à l’aide de la console SCOM, de l’outil MP Author ou d’un notepad, mais cela peut rapidement devenir très répétitif et inutilement consommateur en temps.

En effet, à l’aide de Visual Studio (qui est disponible en « community edition » gratuite depuis maintenant quelques années, plus d’excuses !) et des Authoring Extensions, il est possible d’automatiser en grande partie ce processus !

Commençez par créer un nouveau projet de type Management Pack 2007 R2 (nul besoin de sélectionner 2012 car nous ne ferons rien qui le justifie ici, et cela permet de conserver la rétrocompatibilité du MP) :

clip_image002

Dans l’explorateur de solutions, faites un clic-droit sur le nom de votre projet et sélectionnez ajouter > nouvel élément.

clip_image004

Sélectionnez Snippet Template, nommez-le et cliquez sur ajouter :

clip_image006

Un bloc de code pré-rempli apparaît (il s’agit du template par défaut, un règle de collecte de compteur de performance; mais rien ne vous empêche d’y substituer votre propre code comme nous le verrons plus loin) :

clip_image008

On remarque immédiatement que les balises les plus couramment modifiées lors de la création d’un MP (ID de la règle, cible, nom du compteur, fréquence de collection…) apparaissent surlignées en jaune, et que leur valeur est quelque peu inhabituelle : il s’agit en fait de variables, qui seront remplacées à la volée lors de l’étape suivante.

Ces variables sont de trois types : #text (une simple chaine de caractères), #choice (une liste déroulante) et #alias (elles permettent de résoudre automatiquement l’alias vers vos MP référencés).

Voyons donc maintenant comment alimenter ces variables.

Retournez dans ajouter > nouvel élément, mais sélectionnez cette fois Snippet Data :

clip_image010

Pour l’instant, cela ne crée rien de bien utile :

clip_image012

Cliquez sur Select snippet type et sélectionnez le Snippet Template préalablement créé :

clip_image014

Cette fois-ci, différentes colonnes sont présentes (elles correspondent aux différentes variables présentes dans le template), et deux possibilités nous sont offertes : ajouter des données manuellement (click here to add a new item) ou les importer depuis un fichier CSV (bouton Import from CSV file) :

clip_image016

Commençons par la première possibilité. En cliquant sur click here to add a new item, une ligne vierge apparait. A vous de renseigner les différents champs :

clip_image018

Imaginons maintenant que nous ayons des dizaines de compteurs à collecter via des règles différentes : les ajouter à la main l’un après l’autre de cette facon reste beaucoup plus pratique (et plus propre !) que de créer les règles les unes après les autres dans la console SCOM, mais on peut faire encore plus rapide à l’aide d’un fichier CSV :

clip_image020

Cliquez sur Import from CSV file et sélectionnez votre fichier CSV. Les valeurs qu’il contient sont automatiquement ajoutées à votre Snippet :

clip_image022

Une fois que vous avez entré les valeurs pour toutes les règles que vous souhaitez créer, cliquez sur enregistrer clip_image024 .

Ici, une erreur se produit car le MP System.Performance.Library est référencé dans le Snippet Template, mais pas dans le projet :

clip_image026

Il faut donc l’ajouter : clic-droit sur References > ajouter dans l’explorateur de solutions et sélectionnez le fichier .mp manquant. Vous pouvez le retrouver sur votre serveur SCOM, ou directement dans le dossier d’installation des VSAE pour les MP les plus communs (C:\Program Files (x86)\System Center Visual Studio Authoring Extensions\References\OM2007R2\Microsoft.Windows.Library.mp )

clip_image027

Répétez l’opération pour chaque MP référencé manquant, puis cliquez à nouveau sur Sauvegarder.

Un nouveau fichier doit apparaître dans l’arborescence de votre explorateur de solutions :

clip_image029

Ouvrez le : il contient le code correspondant à toutes vos règles, généré automatiquement en fonction de vos paramètres d’entrée :

clip_image031

Libre à vous maintenant de laisser libre cours à votre imagination pour créer vos propres Snippet Template correspondant à des moniteurs d’évènements, des scripts vbs etc…

Pour cela, rien de plus simple : recopiez vos bouts de codes en reprenant la nomenclature vue ci-dessus pour les variables, créez un nouveau Snippet de Data et alimentez-le à l’aide d’un fichier csv ou manuellement, comme nous venons de le voir.

clip_image033 Attention : si lors de vos développements, vous utilisez des colonnes contenant « true » ou « false » (par exemple si vous souhaitez définir si une règle ou un moniteur sera activé ou non par défaut), il faut obligatoirement que ces valeurs soient écrites en minuscules ; vous rencontrerez une erreur lors de la sauvegarde dans le cas contraire.

Une fois ces fragments de code obtenus, vous pouvez soit continuer votre développement dans Visual Studio et générer votre MP lorsqu’il est terminé, soit les intégrer par copier/coller dans le code XML d’un MP existant que vous souhaitiez enrichir.

Un grand merci au maitre SCOM Kevin Holman pour l’idée originale de cet article ainsi que pour l’ensemble de son œuvre :)

Powershell/Azure/Orchestrator : Formatage des volumes additionnels

 

Lors de la création d’une machine virtuelle, on ne se contente en général pas d’un seul « disque dur » (vhd/vmdk). Il est d’usage de conserver le volume principal pour le système, et d’ajouter un ou plusieurs volumes pour les données, les sauvegardes…

Lors de la création de la VM, ces volumes y sont bien rattachés mais ils sont dans un état « brut » : non initialisés, ni partitionnés, ni formatés, ni nommés, et ne disposant pas de lettre de lecteur.

Et si ces opérations peuvent s’avérer fastidieuses lorsqu’il s’agit d’un déploiement manuel, elles deviennent inacceptables lorsqu’il s’agit de VM déployées automatiquement via un portail self-service déclenchant un processus d’orchestration : la VM doit être livrée « prête à fonctionner » à l’utilisateur qui en a fait la demande.

Heureusement, le vénérable outil diskpart peut être scripté, automatisant ainsi le procédé.

Le script powershell que je vous propose ci-dessous doit être exécuté en tant qu’administrateur local, dès que la VM est démarrée. Il détecte tous les disques qui ne disposent d’aucune partition, les initialise, les partitionne (une seule partition primaire), les formate, les renomme DATAxxx et leur attribue la première lettre disponible.

$datadisks = get-wmiobject win32_diskdrive | where partitions -eq 0

$i = 1

foreach ($disk in $datadisks) {

$diskID = $disk.index

$diskname = "DATA" + $i

$dpscript = @"

SELECT DISK $diskID

ATTRIBUTES DISK CLEAR READONLY

CREATE PARTITION PRIMARY

FORMAT fs=ntfs quick label=$diskname

ASSIGN

"@

$i++

$dpscript | diskpart

}

Il ne reste plus qu’à intégrer ce script à votre processus de déploiement, qu’il s’agisse d’une tâche post-installation dans SCVMM ou d’un runbook Orchestrator :

clip_image002

Il s’agit ici d’un déploiement de VM dans Azure ne disposant que d’un compte administrateur local hors domaine. On commence par monter le disque D : de la VM (disque temporaire créé automatiquement) en tant que partage, puis on y crée le script proposé ci-dessus, on l’exécute à l’aide de la commande powershell.exe -ExecutionPolicy ByPass "& ""D:\diskpart.ps1"""  et on termine en démontant le partage réseau.

L’exécution du script ne prend que quelques minutes même avec plusieurs volumes à formater, et il s’adapte automatiquement quel que soit leur nombre.

Powershell/Azure : utiliser un proxy dans un script

 

Certains scripts powershell peuvent nécessiter un accès au Web, comme par exemple ceux utilisés pour piloter un tenant Azure.

Or, la majorité des organisations utilisent aujourd’hui des proxy pour contrôler ces accès à Internet et il est préférable d’éviter autant que possible les exceptions à cette règle, y compris lorsque c’est un script qui a besoin de se connecter.

Certains cmdlet ont en plus une facheuse tendance à ignorer les paramètres de proxy de l’utilisateur qui les exécute (c’est le cas des cmdlet Azure Powershell tels que Login-AzureRmAccount), et il n’est pas toujours possible ou souhaitable de définir un proxy au niveau du système, via la commande netsh winhttp set proxy…

Heureusement, il est possible de spécifier ces paramètres directement au sein du script !

Dans un premier temps, il est nécessaire de spécifier l’adresse du Proxy :

$proxyAddress = "http://1.2.3.4:8080"

$proxyUri = new-object System.Uri($proxyAddress)

[System.Net.WebRequest]::DefaultWebProxy = new-object System.Net.WebProxy ($proxyUri, $true)

Si le proxy accepte les connexions anonymes, cela peut suffire.

Autrement, il sera nécessaire de spécifier des credentials autorisés à s’y connecter. Dans ce cas, deux possibilité :

- Soit vous ré-utilisez les credentials de l’utilisateur qui exécute le script :

[System.Net.WebRequest]::DefaultWebProxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials

- Soit vous utilisez les credentials d’un autre compte  :

$proxyAccountName = "domain\user"

$proxyPassword = ConvertTo-SecureString "PASSWORD" -AsPlainText -Force

$proxyCred = New-Object System.Management.Automation.PSCredential($proxyAccountName, $proxyPassword)

[System.Net.WebRequest]::DefaultWebProxy.Credentials = $proxycred

En plaçant ces quelques lignes avant toute exécution de cmdlet nécessitant un accès au Web, vous ne devriez plus rencontrer de problème!

Azure : Récupérer l’adresse IP d’une machine virtuelle

 

Il peut parfois s’avérer nécessaire dans un script de récupérer l’adresse IP d’une VM Azure alors que celle-ci n’est pas enregistrée dans le DNS.

Dans Azure « classic» (l’ancienne version), cette information était renvoyée directement à l’aide du cmdlet Get-AzureVM :

clip_image002

Malheureusement, pour les VM créées dans Azure Resource Manager (Azure RM, la « nouvelle » version), le cmdlet Get-AzureRmVM fonctionne différemment et ne renvoie plus directement cette information :

clip_image004

Il renvoie par contre une information intéressante : l’ID de la carte réseau associée à la VM, via la propriété NetworkInterfaceIDs :

clip_image006

La fin de cet ID représente le « display name » de la carte réseau, qui va nous permettre de retrouver les propriétés détaillées de cette carte à l’aide du cmdlet Get-AzureRmNetworkInterface :

clip_image008

Dans ces propriétés détaillées, une en particulier nous intéresse : IpConfigurationsText.
Comme son nom l’indique, elle contient le détail de la configuration Ip de la carte réseau, dont la PrivateIpAddress qui nous intéresse :

clip_image010

Afin d’automatiser ce processus, j’ai réalisé une fonction Get-AzureRmVMIP qui prend en entrée le nom de la VM et celui de son Resource Group, et qui renvoie le nom de la carte réseau et son IP :

clip_image012

Fonction dont voici le code source, que vous pouvez réutiliser ou adapter à votre guise dans vos propres scripts.

Function Get-AzureRmVMIP

{ param

(

[Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]

[string]

$Name,

[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]

[string]

$ResourceGroupName

)

Process

{

$VM = Get-AzureRmVM -Name $Name -ResourceGroupName $ResourceGroupName

$NICs = get-AzureRmNetworkInterface -name $vm.NetworkInterfaceIDs.split("/")[-1] -ResourceGroupName $ResourceGroupName

$VMIPAddresses = @()

foreach ($NIC in $NICs) {

$VMIPAddresses += @{$NIC.Name = $NIC.IpConfigurations.PrivateIpAddress}

}

Return $VMIPAddresses

}

}

Orchestrator – Déployer des Integration Packs en DMZ

 

Dans le cadre d’un déploiement d’Orchestrator 2012 contenant des Runbook Servers dans un réseau isolé (DMZ) du reste de l’infrastructure, le déploiement des Integration Packs peut devenir problématique.

En effet, ces derniers sont normalement enregistrés dans le Management Server (Register IP) puis poussés vers les Runbook Servers et Runbook Designers (Deploy IP) à travers le réseau à l’aide de la console Deployment Manager, située sur le serveur hébergeant le rôle Management Server.

clip_image002

Lorsque les flux réseau sont bloqués, il n’est donc pas possible de pousser les Integration Packs vers leur destination

Deux solutions sont alors disponibles : installer les IP localement sur les serveurs en DMZ, ou ouvrir les flux nécessaires.

Installation locale

Prenons l’exemple de l’intégration pack pour Active Directory.

Il est dans un premier temps nécessaire de l’enregistrer (Register IP) tout à fait classiquement, je ne détaillerais donc pas cette étape ici :

clip_image004

Lors de ce processus, l’Integration Pack est copié sous forme de fichier MSI dans le dossier C:\Program Files (x86)\Common Files\Microsoft System Center 2012\Orchestrator\Management Server\Components\Objects :

clip_image006

Copiez ce fichier vers le Runbook Server ou le Runbook Designer de DMZ, puis exécutez-le.

L’installeur se déroule et se ferme sans aucune intervention de votre part, mais une fois terminé, l’Integration Pack doit être visible dans le Deployment Manager et ses activités doivent apparaitre dans le Runbook Designer (il est nécessaire de le relancer s’il était déjà ouvert) :

clip_image007

clip_image009

Ouverture des flux

Là aussi, il est tout d’abord nécessaire d’enregistrer l’Integration pack de façon classique (Register IP)

Lors du déploiement par la console Deployment Manager, les protocoles utilisés sont SMB et WMI, c’est-à-dire les habituels ports 135 et 445 en TCP, qu’il faudra donc ouvrir entre votre LAN et la DMZ où se trouvent vos Runbook Servers ou Runbook Designers.

Il est bien entendu également nécessaire d’ouvrir ces ports dans un éventuel firewall (Windows ou autre), ainsi que d’autoriser l’accès réseau à l’exécutable %SystemRoot%\SysWOW64\OrchestratorRemotingService.exe ; autrement le déploiement ne fonctionnera pas.

Le déploiement se fait ensuite via la console Deployment Manager de la même manière que si les serveurs cible étaient dans le LAN.

Complément

Attention toutefois, dans le cadre de l’utilisation d’un environnement Orchestrator disposant de serveurs Runbook à la fois dans le LAN et dans la DMZ : il devient alors primordial de bien déterminer quel Runbook devra tourner sur quel serveur, soit à l’aide des propriétés du Runbook à exécuter, soit via l’activité Invoke Runbook du runbook parent qui appelle le Runbook à exécuter (il est dans ce cas possible d’en indiquer plusieurs en les séparant par des point-virgules) :

clip_image011 clip_image013

Orchestrator - Changer les credentials des comptes de service

 

Il peut s’avérer nécessaire de changer les credentials des comptes de service utilisés par Orchestrator, lors d’incidents habituels dans le cycle de vie du produit (perte du mot de passe, politique de sécurité…).

Cependant, cela nécessite une reconfiguration à plusieurs niveaux :

Compte de service Orchestrator

Le premier niveau est le changement de credentials du compte utilisé pour exécutez les services Orchestrator (Management Service, Runbook Services…)

Dans un premier temps, il faut remplacer les mots de passe des services qui se trouvent sur chaque serveur hébergeant un rôle Orchestrator (Management, Runbook…).

Tout ou partie des services suivants peuvent être présents, en fonction des rôles attribués au serveur :

clip_image002

Pour modifier le compte utilisé par ces services, double-cliquez sur chacun d’eux et ouvrez l’onglet Log On :

clip_image004

Indiquez le nouveau login et/ou mot de passe puis cliquez sur OK.

Il est ensuite également nécessaire de modifier le compte utilisé par le pool d’application IIS :

Dans la console IIS Manager, ouvrez les Applications Pools et sélectionnez System Centez 2012 Orchestrator Web Features.

clip_image006

Faire un clic-droit et sélectionnez Advanced Settings.

clip_image008

Dans le champ Identity, cliquez sur l’icône « … »

clip_image010

Cliquez sur Set

clip_image012

Indiquez le nouveau login et/ou mot de passe du compte de service, puis cliquez sur OK dans chacune des fenêtres ouvertes.

Compte d’accès à la base SQL

Le second niveau concerne la modification des credentials du compte utilisé par Orchestrator pour se connecter à sa base SQL : il ne s’agit pas nécessairement du compte de service utilisé précédemment.

Lorsqu’il est modifié, la configuration d’Orchestrator doit être également modifiée sur l’ensemble des serveurs exécutant le rôle Runbook Server et/ou le rôle Web Service.

Runbook Server

Lancez la console Data Store Configuration :

clip_image014

Indiquez le nom du serveur SQL dans le champ Server et les credentials de connexion à l’instance SQL dans les champs Authentication Credentials., puis cliquez sur Next.

clip_image016

Cochez Use an existing data store et sélectionnez la base Orchestrator, puis cliquez sur Finish.

N’oubliez pas de répéter cette opération sur chacun des serveurs de Runbook.

Web Service

Le fichier de configuration du webservice est chiffré, il est donc nécessaire de le déchiffrer avant de le modifier.

Ouvrez un prompt de commande en mode administrateur et exécutez la commande

C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pdf "connectionStrings" "D:\Program Files (x86)\Microsoft System Centez 2012 R2\Orchestrator\Web Service\Orchestrator2012"

clip_image018

Dans la console IIS Management, ouvrez l’arborescence Sites/Microsoft System Centez 2012 Orchestrator Web Service/Orchestrator2012.

Ouvrez la configuration des Connection Strings

clip_image020

Ouvrez Orchestrator Context et modifiez les informations de connexion à la base de données (serveur, instance, credentials…) en fonction du besoin.

clip_image022

Chiffrez à nouveau le fichier de configuration à l’aide de la commande C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pef "connectionStrings" "D:\Program Files (x86)\Microsoft System Centez 2012 R2\Orchestrator\Web Service\Orchestrator2012"

clip_image024

Enfin, redémarrez IIS à l’aide de la commande iisreset.exe

Ca y est, nous avons désormais fait le tour de cette procédure, assez fastidieuse il est vrai… et malheureusement pas automatisable sous forme de runbook Clignement d'œil

Azure - récupérer l’accès à une VM quand la carte réseau a été désactivée

 

Si vous utilisez Azure pour déployer des VM, vous n’êtes pas sans savoir qu’il n’existe aucun moyen de se connecter à une console « directe » (en mode KVM/Ilo/Idrac).

Les seules possibilités d’accès sont celles basées sur un protocole réseau, par exemple Remote Desktop sous Windows.

Mais alors, que se passe-t-il si vous avez désactivé la carte réseau ? Il n’existe à première vue plus aucun moyen de prendre la main sur votre VM…

Un simple redémarrage ne suffit évidemment pas.

Mais une astuce simple permet de se sortir de ce mauvais pas :

Ouvrez l’ancien portail azure ( https://manage.windowsazure.com ) (au moment de la rédaction de ce billet, la manipulation ne fonctionne pas avec le nouveau).

Ouvrez les propriétés de votre VM et modifiez sa taille (size) en choisissant un autre Tier que celle où elle se trouve déjà (Standard vers Basic, par exemple) :

clip_image002

Le redimensionnement prend quelques secondes et est suivi d’un redémarrage de la VM :

clip_image004

clip_image006

clip_image008

Patientez encore quelques minutes, le temps que la VM termine de démarrer et qu’elle installe les pilotes de la « nouvelle » carte réseau, puis qu’elle monte les services réseau etc.

Vous devriez maintenant pouvoir vous connecter via le Bureau à distance à votre VM, avec son ancienne IP !

On peut également retrouver dans le journal d’événements une trace de l’installation de cette nouvelle carte réseau :

clip_image010

SCOM – Utiliser un Run As dans un script

Dans un précédent billet, je décrivais comment Ajouter un Run-As profile à un moniteur ou à une règle, afin de les faire s’exécuter avec des credentials autres que Local System.

Je vous propose ici un complément sur le même sujet, qui vous permettra d’utiliser en paramètre d’un script un couple login/mot de passe stocké dans un Run-As account, vous permettant ainsi de ne pas coder ces credentials en dur dans le script pour plus de sécurité et de maintenabilité.

Tout le début de cette procédure est exactement identique à celle proposée dans le précédent billet, vous pouvez donc vous y référer si vous ne disposez pas encore d’un couple run as profile/run as account contenant vos credentials.
Notez toutefois qu’il faut ici créer un un run as account de type Simple Authentication et non pas un compte Windows.

Une fois ceci fait et en possession de l’ID du Run As profile, nous pouvons revenir à notre moniteur ou règle de type script.

Dans les paramètres passés au script, il est alors possible de faire appel à ce profil à l’aide la syntaxe

$RunAs[Name="Test.Monitors.RunAsProfile"]/Username$ pour le login et

$RunAs[Name="Test.Monitors.RunAsProfile"]/Password$ pour le mot de passe.

Le login et le mot de passe (automatiquement déchiffré et donc passé en clair au script) seront alors passés au script lors de son exécution.

clip_image002

Il ne reste alors plus qu’à les déclarer et les assigner à une variable dans le script, puis à les utiliser par exemple ici pour se connecter à un serveur SQL :

Dim Username, Password, sConnectString
Username = WScript.Arguments(0)
Password = WScript.Arguments(1)
[…]
sConnectString = "Driver={SQL Server}; Server=SQL\TEST; Database=TESTDB;uid=" & Username & ";password=" & Password
[…]

On le voit, le mot de passe n’est jamais codé en clair dans le script et pour le modifier, il suffit de modifier le Profil et non pas le script.

SCOM - Moniteur de performance multi-instances

Lors de la création d’un moniteur de performance, il peut arriver qu’il soit nécessaire de superviser plusieurs instances du compteur et d’alerter lorsque n’importe laquelle de ces instances dépasse le seuil paramétré.

La solution qui vient alors immédiatement à l’esprit est alors d’utiliser les wildcard (jokers) dans le nom de l’instance :

clip_image002

Malheureusement, voici ce qui se produit dans ce cas :

clip_image004

clip_image006

Le moniteur détecte bien que l’instance w3wp dépasse le seuil paramétré et passe donc en Critical, mais instantanément après le moniteur détecte que l’instance w3wp#10 est elle toujours sous le seuil et il repasse donc en Healthy : la vérification se fait pour chaque instance du compteur l’une après l’autre, et si un seul d’entre eux n’est pas en critical, le moniteur repasse en vert immédiatement.

Et ce manège recommence à chaque exécution du moniteur…

Une première bonne solution consiste alors à utiliser une variable à la place d’un wildcard en tant qu’Instance.

Prenons l’exemple d’un moniteur de performance qui serait ciblé sur la classe Logical Disk.

Cette classe dispose de propriétés, dont plusieurs correspondent au nom des instances de compteurs :

clip_image007

On peut alors réutiliser une de ces variable dans le champ Instance de l’assistant de création du moniteur, à l’aide de la petite flèche située à sa droite :

clip_image008

On aura donc un moniteur pour chaque instance SCOM de la classe logical disk, ciblé uniquement sur l’instance du compteur de performance qui lui correspond.

Il arrive cependant qu’aucune classe SCOM ne dispose de propriétés utilisables en tant que variable,  typiquement en reprenant le premier exemple du process w3wp.exe.

Dans ce cas, une autre solution existe : le module de détection de condition (condition detection module) System.LogicalSet.ExpressionFilter introduit dans SCOM 2007 R2 permet de déterminer quand arrêter le traitement des données provenant d’une datasource lorsque celle-ci renvoie plusieurs résultats (ce qui est le cas quand un System.Performance.DataProvider est ciblé sur plusieurs instances d’un compteur perfmon).

Autrement dit, en utilisant ce module, les valeurs de chaque instance du compteur sont analysées l’une après l’autre. Dès qu’une de ces instances dépasse le seuil défini, le moniteur passe en Critical et s’arrête sans analyser les instances suivantes, empêchant donc le moniteur de repasser en Healthy.

L’utilisation de ce module n’est toutefois pas possible directement depuis la console SCOM et nécessite de créer son propre MonitorType :

<TypeDefinitions>

<MonitorTypes>

<UnitMonitorType ID="MultipleInstance.Perf.MonitorType" Accessibility="Public">

<MonitorTypeStates>

<MonitorTypeState ID="AboveThreshold" NoDetection="false" />

<MonitorTypeState ID="BelowThreshold" NoDetection="false" />

</MonitorTypeStates>

<Configuration>

<xsd:element name="ComputerName" type="xsd:string" />

<xsd:element name="CounterName" type="xsd:string" />

<xsd:element name="ObjectName" type="xsd:string" />

<xsd:element name="InstanceName" type="xsd:string" />

<xsd:element name="AllInstances" type="xsd:boolean" />

<xsd:element name="Frequency" type="xsd:unsignedInt" />

<xsd:element name="Threshold" type="xsd:double" />

</Configuration>

<OverrideableParameters>

<OverrideableParameter ID="Frequency" Selector="$Config/Frequency$" ParameterType="int" />

<OverrideableParameter ID="Threshold" Selector="$Config/Threshold$" ParameterType="double" />

</OverrideableParameters>

<MonitorImplementation>

<MemberModules>

<DataSource ID="DS_PerfData" TypeID="Performance!System.Performance.DataProvider">

<ComputerName>$Config/ComputerName$</ComputerName>

<CounterName>$Config/CounterName$</CounterName>

<ObjectName>$Config/ObjectName$</ObjectName>

<InstanceName>$Config/InstanceName$</InstanceName>

<AllInstances>$Config/AllInstances$</AllInstances>

<Frequency>$Config/Frequency$</Frequency>

</DataSource>

<ConditionDetection ID="BelowThresholdDetection" TypeID="SystemLibrary7585010!System.LogicalSet.ExpressionFilter">

<Expression>

<SimpleExpression>

<ValueExpression>

<XPathQuery Type="Double">Value</XPathQuery>

</ValueExpression>

<Operator>LessEqual</Operator>

<ValueExpression>

<Value Type="Double">$Config/Threshold$</Value>

</ValueExpression>

</SimpleExpression>

</Expression>

<EmptySet>Passthrough</EmptySet>

<SetEvaluation>All</SetEvaluation>

</ConditionDetection>

<ConditionDetection ID="AboveThresholdDetection" TypeID="SystemLibrary7585010!System.LogicalSet.ExpressionFilter">

<Expression>

<SimpleExpression>

<ValueExpression>

<XPathQuery Type="Double">Value</XPathQuery>

</ValueExpression>

<Operator>Greater</Operator>

<ValueExpression>

<Value Type="Double">$Config/Threshold$</Value>

</ValueExpression>

</SimpleExpression>

</Expression>

<EmptySet>Block</EmptySet>

<SetEvaluation>Any</SetEvaluation>

</ConditionDetection>

</MemberModules>

<RegularDetections>

<RegularDetection MonitorTypeStateID="BelowThreshold">

<Node ID="BelowThresholdDetection">

<Node ID="DS_PerfData" />

</Node>

</RegularDetection>

<RegularDetection MonitorTypeStateID="AboveThreshold">

<Node ID="AboveThresholdDetection">

<Node ID="DS_PerfData" />

</Node>

</RegularDetection>

</RegularDetections>

</MonitorImplementation>

</UnitMonitorType>

</MonitorTypes>

</TypeDefinitions>

On constate que ce module se configure très simplement à l’aide de deux balises xml : EmptySet et SetEvaluation.

EmptySet indique le traitement à appliquer : Passthrough (on continue le traitement des données vers les modules suivants dans le workflow, c’est le mode par défaut) ou Block (qui arrête le traitement du wokflow).

SetEvaluation indique si les données de chaque instance doivent correspondre (All), ou si une seule suffit (Any).

Dans l’exemple ci-dessus, on demande donc d’arrêter le traitement (Block) dès que n’importe quelle instance du compteur (Any) passe au dessus du seuil défini.

Ne reste alors plus qu’à implémenter le Moniteur à proprement parler :

<UnitMonitor ID="w3wp.process.privatebytes.monitor" Accessibility="Public" Enabled="false" Target="SharePoint2!Microsoft.SharePoint.2013.SPServiceInstance.Excel" ParentMonitorID="Health!System.Health.AvailabilityState" Remotable="true" Priority="Normal" TypeID="MultipleInstance.Perf.MonitorType" ConfirmDelivery="true">

<Category>PerformanceHealth</Category>

<AlertSettings AlertMessage="w3wp.process.privatebytes.monitor_AlertMessageResourceID">

<AlertOnState>Error</AlertOnState>

<AutoResolve>true</AutoResolve>

<AlertPriority>Normal</AlertPriority>

<AlertSeverity>Error</AlertSeverity>

</AlertSettings>

<OperationalStates>

<OperationalState ID="AboveThreshold" MonitorTypeStateID="AboveThreshold" HealthState="Error" />

<OperationalState ID="BelowThreshold" MonitorTypeStateID="BelowThreshold" HealthState="Success" />

</OperationalStates>

<Configuration>

<ComputerName>$Target/Host/Property[Type="MicrosoftWindowsLibrary7585010!Microsoft.Windows.Computer"]/NetworkName$</ComputerName>

<CounterName>Private Bytes</CounterName>

<ObjectName>Process</ObjectName>

<InstanceName>w3wp*</InstanceName>

<AllInstances>false</AllInstances>

<Frequency>300</Frequency>

<Threshold>2000000000</Threshold>

</Configuration>

</UnitMonitor>

Et cette fois-ci le moniteur ne bagotte plus, tant que n’importe laquelle des instances du compteur sera au dessus du seuil, le moniteur restera en Critical :

clip_image009

Pour aller plus loin : https://msdn.microsoft.com/en-us/library/hh442318.aspx?f=255&MSPPError=-2147217396

SCCM 2012 – Un déploiement s’exécute en boucle / L’agent se réinstalle toutes les 5h

 

Après le déploiement d’une tâche de reboot via SCCM (un simple de shutdown /r à intervalle planifiée sur une collection de serveurs), je me suis rendu compte que quelques serveurs rebootaient en boucle toutes les 5h.

Après mal de questionnement et d’analyse de log, je me suis aperçu que l’agent SCCM se réinstallait à la même fréquence, ce qui expliquait la répétition de la tâche de reboot étant donné son paramétrage assez « souple » (pas de maintenance window…).

Restait à identifier la raison de cette réinstallation… Ni les logs, ni la console SCCM ne contenaient d’information utile.

Pire, même en désactivant le service de l’agent (bloquant ainsi toute communication avec le serveur), il continuait à se réinstaller (et donc à se réactiver) !

La solution est finalement venue comme souvent d’une recherche sur internet, après avoir trouvé les bons mots-clés… Et le coupable s’avère être une tâche planifiée créée par CCMSETUP lors du premier déploiement de l’agent SCCM, dans le dossier Microsoft/Configuration Manager/Microsoft/Configuration Manager (oui, deux fois !) :

clip_image001

Cette dernière est paramétrée pour se relancer toutes les 5h et sert normalement lorsque CCMSETUP n’arrive pas à contacter le serveur SCCM, afin de reprendre le déploiement de l’agent ultérieurement.

Sauf que pour une raison quelconque (la répétition de l’arborescence Microsoft/Configuration Manager) peut faire penser à un bug qui créerait la tâche au mauvais endroit), il arrive que cette tâche planifiée ne soit jamais supprimée, et l’agent se réinstalle donc en boucle indéfiniment…

La solution est alors toute trouvée : il suffit de supprimer (ou au minimum de désactiver) cette tâche planifiée et tout rentre dans l’ordre!