PI Services

Le blog des collaborateurs de PI Services

Zabbix – Supervision basique d’une URL


Zabbix propose plusieurs manière de superviser des URL. L’exemple ci-dessous propose d’utiliser un ‘Web Scenario’ pour la supervision d’une URL simple (ici www.google.fr).

on commence par créer un template vide qui contiendra la configuration:

image


image


image

NB: Le nom du Host group associé est arbitraire.

Cliquer Add.

image

Le template vide est crée.


image

Cliquer “Create Web Scenario”


image

Name: Check Google

Agent: On positionne Zabbix. ce champs permet de selectionner plusieurs type de client http/navigateur.

Cliquer Steps.


image

Dans la zone Steps, cliquer sur Add.


image

name: Google base page

URL: http://www.google.fr

Required Status codes: 200


image

image

Cliquer Add

image

Le Web scenario est crée.


image

On applique (Link) le template au host devant effectuer le check de supervision.


image


image

Apres quelques minutes les données remonte dans la liste des “Latest data” du host concerné. on voit ici que le code HTTP renvoyé est bien 200 (OK)

On crée a présent un trigger (alerte) en charge declencher une alerte sur le cas ou le code HTTP serait different de 200.

image

image

Dans les propriétés du template, cliquer Triggers


image

cliquer en haut a droite Create Trigger


image

Name: Google Site KO

Clquer sur Add a coté de la zone Expression pour construire la condition de declenchement.


image

Cliquer sur Select pour aller rechercher l’item crée precedemment.


image

Selectionner “Response code for step “Google base page”…”


image

Laisser selectionné la fonction “last()”.

Result: <> 200

cliquer Insert.


image

A titre d’indication ajouter le nom de l’url surveillée dans le champ URL.

Cliquer Add.


image

Le trigger est maintenant actif.

Teams : Customiser ses effets d'arrière plan

Si vous avez déjà utilisé Teams en réunion, vous avez pu remarquer des évolutions au fil du temps (floutage de l'arrière plan, effets d'arrière plan...)

Aujourd'hui je vous donne un petit tips pour modifier votre image d'arrière plan et vous démarquer de vos collègues.

  1. Sélectionnez une image qui vous plait ou un fond d'écran.
  2. Copiez la.
  3. Collez la dans le répertoire "C:\Users\votrenom\AppData\Roaming\Microsoft\Teams\Backgrounds\Uploads"
  4. Dans Teams durant votre conversation vidéo sélectionnez les 3 petits points "..." (autres actions)
  5. Puis sélectionnez "Afficher les effets d'arrière plan"

  1. Dans "Paramètres d'arrière plan" descendez tout en bas et vous verrez vos images. 

 

Et voila, have fun.

Sharepoint Online : Windows Powershell ISE figé

Avez vous déjà rencontré l'expérience de la console Powershell ISE qui fige lorsque vous utilisez Sharepoint Online et le MFA ?

Je sais c'est désagréable, surtout quand un script tourne depuis un moment, voici donc un petit contournement pour corriger ce problème.

  1. Créez sur votre bureau un raccourcis de Powershell ISE.
  2. Sélectionnez le, faites un clic droit et enfin sélectionnez "Propriétés".
  3. Dans le champs "Cible", ajoutez " -Mta" à la fin.

Maintenant lorsque vous exécuterez la console, lancez la via ce raccourcis et les problèmes de console qui fige seront un mauvais souvenir.

SquaredUp - Récupérer un dashboard bloqué

Lorsque l’on s’aventure dans la modification manuelle du code JSON d’un dashboard, une mauvaise manipulation est vite arrivée et peut résulter dans le blocage complet du dashboard : il n’est plus possible de le modifier, de le sauvegarder ou de revenir en arrière ; tous les boutons sont inopérants.

Heureusement, il est possible de se sortir de ce mauvais pas sans devoir totalement supprimer le dashboard !

En effet, lorsqu’ils sont en cours de modification, les dashboards sont stockés temporairement sur le serveur qui héberge SquaredUp dans le dossier C:\inetpub\wwwroot\SquaredUpv4\User\Packages\VotreLogin\dashboards sous forme de fichier JSON que vous pouvez ouvrir et modifier avec n’importe quel éditeur de texte.

Il vous suffit donc de corriger votre erreur, enregistrer le fichier, rafraichir le dashboard dans la console SquaredUp et le tour est joué, vous avez récupéré la main !

 

 

SquaredUp - Matrix Tiles et valeur absente

 Suite à mon précédent article d’introduction à SquaredUp, il est maintenant temps de s’intéresser à quelques-uns des problèmes rencontrés lors de la construction de quelques dashboards ; en particulier ici lors de l’utilisation de tuiles de type « Matrix ».

Les tuiles « Matrix » sont très intéressantes car elles permettent d’afficher plusieurs informations sous différents formats (état de l’objet, état d’un moniteur, sparkline de performance, SLA propriété de l’objet…) sur une même ligne :

Certaines subtilités ne sont cependant pas documentées, et on peut rapidement se casser les dents sur une opération qui semblait pourtant simple au premier abord.

Propriété de l’objet

 

Il est possible d’afficher une colonne contenant simplement une propriété de l’objet au format texte. Dans la capture ci-dessus, on affiche par exemple la propriété DomainDnsName de la classe Microsoft.Windows.Computer.

La syntaxe est très simple (exemple fourni dans la documentation de SquaredUp) :

{
    "title": "Domain DNS",
    "_type": "celltile/text",
    "config": {
        "display": {
            "contentTemplate": "{{properties.domainDnsName}}"
        }
    }
}


Ce que n’indique pas clairement la documentation, c’est l’obligation de respecter strictement la casse du nom de la propriété… à l’exception de son premier caractère, qui doit toujours être écrit en minuscule.

L’exemple le montre bien, mais sans explication écrite c’est loin d‘être évident !

 

Valeur calculée

SquaredUp utilise la syntaxe Mustache et supporte donc presque toutes les fonctions de transformation issues de Javascript.

Il est donc en théorie possible de ne garder que deux décimales après la virgule lors de l’affichage d’un compteur de performance avec la fonction ToFixed :

"labelTemplate": "{{ (value).ToFixed(2) }}"

 

Malheureusement, cela résulte en une colonne vide.

Et la raison est identique au point précédent : il est impératif d’utiliser la casse exacte de la syntaxe Javascript… sauf le premier caractère qui doit obligatoirement être en minuscule.

La syntaxte suivante fonctionne donc :

"labelTemplate": "{{ (value).toFixed(2) }}"

 

Simple à corriger… mais rageant lorsque l’on bute sur le problème !

 

Valeur d’un objet hébergée dans une colonne « bar »

L’exemple donné par la documentation semble encore une fois d’une simplicité enfantine :

 

{
    "title": "Memory Usage Bar",
    "_type": "celltile/bar",
    "config": {
        "source": {
            "objectname": "Memory",
            "countername": "PercentMemoryUsed"
        },
        "display": {
            "valueTemplate": "{{(value ? Math.floor(value) : 0)}}"
        }
    }
}

Le nom du compteur, éventuellement un peu de formatage de la valeur via une fonction Javascript et voilà.

Mais lorsque la Matrix est ciblée sur une classe hébergée par une autre, cela ne fonctionne pas : la colonne est vide.

Un peu plus loin dans la documentation, dans la section concernant les sparklines, on trouve l’information suivante : lorsque  la tuile est scopée sur un objet hébergé tel qu’un disque, une base de données ou un site web, il faut modifier la configuration du groupement :

"transforms": [
    {
        "operator": "group",
        "parameters": {
            "keys": [
                "managedEntityId"
            ]
        }
    },
    {
        "operator": "merge",
        "parameters": {
            "sourceKey": "id",
            "targetKey": "key.managedEntityId"
        }
    }
]

 

Il semble alors naturel de tenter la même modification pour la sparkline. Malheureusement sans succès…

La solution, qui m’a été apportée par le support de SquaredUp, est la suivante :

"transforms": [
    {
        "operator": "merge",
        "parameters": {
            "sourceKey": "id",
            "targetKey": "managedEntityId"
        }
    }
]



Il s’agit quasiment de la même syntaxe, mais en n’utilisant que le merge.

C’est tout pour aujourd’hui !

SCOM - SquaredUp, le compagnon idéal ?

 

Le problème

Si vous demandez aujourd’hui à un utilisateur de SCOM quelles sont les plus grandes faiblesses du produit, grandes sont les chances qu’il vous cite au minimum la difficulté de créer des Management Packs avancés ainsi que la lourdeur et le manque d’ergonomie de l’interface utilisateur.

Cette dernière est en effet universellement connue pour être lente (même en ayant réalisé toutes les optimisations possibles) et pour offrir une navigation peu intuitive et assez datée, y compris dans les versions les plus récentes du produit.

En découlent donc une frustration et un manque d’efficacité pour les opérateurs de supervision et la quasi impossibilité de faire adopter le produit aux utilisateurs indirects qui pourraient pourtant en bénéficier : les autres membres des services informatiques préfèrent demander à l’opérateur de chercher les données dont ils ont besoin, et les responsables des applications métier n’ont pas de réelle solution pour bénéficier de dashboards synthétiques qui leur permettraient d’obtenir une vision rapide de l’état de santé de leur application.

 

Les solutions

Bien sûr, Microsoft tente depuis déjà de nombreuses versions d’améliorer ces points avec différentes propositions de dashboards censés développer les capacités de présentation du produit (plugin Visio, Widgets dans SCOM 2012, dashboards de la console web HTML 5 depuis la version 1801), mais le résultat de ces efforts est toujours resté très en deca des espérances des utilisateurs.

C’est pourquoi différents éditeurs tiers ont tenté d’apporter une meilleure réponse à ce besoin : historiquement, Savision LiveMaps puis plus récemment SquaredUp. C’est à ce dernier arrivé que nous nous intéressons aujourd’hui, car j’ai eu l’opportunité de le redéployer récemment pour un de mes clients.

 

A quoi ca ressemble ?

Trêve de bavardage, attaquons le sujet par son aspect le plus important : son apparence.

L’interface du produit est des plus moderne, en HTML5 entièrement responsif aussi efficace sur une TV que sur un smartphone et très épurée et efficace.

Chaque dashboard est constitué d’une série de tuiles, chacune contenant un widget parmi les différents types et formats disponibles (alertes, performance, état ;D sous forme de liste, de donut…) et ainsi présenter les informations pertinentes aux différente populations d’utilisateurs :

Décisionnel, avec l’affichage instantané de la disponibilité des SLA de toutes les applications métier :

 

Infrastructure, avec les indicateurs les plus importants pour une technologie donnée (ici pour SQL) :

 

Ou encore métier, avec les indicateurs clés de tous les systèmes qui composent un applicatif :

 

 

Comment ca marche ?

Très simplement ! L’installation ne prend que quelques minutes et est quasi entièrement automatisée. Le seul composant nécessaire est IIS, l’installeur se charge de son déploiement s’il n’est pas présent sur le serveur et il est parfaitement possible d’installer SquaredUp dans un IIS existant (par exemple sur un serveur hébergeant le role Console Web de SCOM).

La configuration ne nécessite ensuite qu’un accès à la base Datawarehouse de SCOM, aucune base additionnelle n’est nécessaire. Toutes les données affichées proviennent de cette base.

Comme quoi il est possible d’avoir un affichage rapide et efficace sans aucune modification des données ou de leur structure… Microsoft devrait en prendre de la graine !

La construction des dashboards se fait ensuite entièrement graphiquement, directement dans la console web. Ils sont en réalités construits en JSON, qu’il est possible de modifier manuellement au besoin.

 

C’est tout ?

Différentes éditions existent, et les plus avancées disposent d’options intéressantes : intégrer des données provenant d’une base SQL externe, d’une requête dans Log Analytics ou du résultat de la requête d’une API REST…

Le produit dispose même d’un module nommé VADA qui permet la construction accélérée d’Applications Distribuées complexes, en détectant automatiquement les connexions TCP entre les différentes couches applicatives (load balancer vers frontal web vers backed vers base de données vers…) à l’aide de netstat exécuté en direct !

Cela ne remplace pas une application distribuée construite à l’aide de découvertes dynamiques par un développeur SCOM chevronné, mais c’est incontestablement plus rapide et pratique que la construction visuelle classique.

 

Ca doit être cher !

Je vous laisserai seul juge de ce point, mais il faut au moins reconnaitre que SquaredUp joue carte sur table en affichant publiquement ses tarifs, ce qui est excessivement rare dans le monde des extensions pour SCOM (plugins et Management Packs d’éditeurs tiers) :

 

A noter également la disponibilité d’une version d’essai au long cours « COVID19 » : 1 mois de fonctionnalités complètes (édition EAM) avec utilisateurs illimités, puis 6 mois d’édition spéciale avec 1 seul utilisateur nommé mais un nombre de dashboards OpenAccess (non cliquables) illimités. L’occasion parfait de tester le produit !

 

Des points négatifs ?

Oui, évidemment, il y en a.

SquaredUp n’a rien d’une solution magique : il ne fait qu’afficher de façon ergonomique et efficace les données collectées par SCOM.

Si votre SCOM est laissé à l’abandon depuis des années, mal ou pas tuné… vous aurez les plus grandes difficultés à obtenir un affichage pertinent. A noter que SquaredUp propose via sa société sœur Cookdown un produit tiers gratuit nommé EasyTune pour aider à résoudre ce point.

La construction des dashboard est parfois trop simple, au point que l’on se prend à regretter l’absence de certaines capacités qui nous semblent pourtant évidentes.

La documentation est claire mais pas toujours suffisamment détaillée.

Le support est par contre toujours très disponible pour vous débloquer et ouvert aux suggestions d’amélioration.

 

Conclusion

Selon moi, SquaredUp devrait être au minimum étudié dans le cadre de tous les déploiements SCOM. Il permet d’apporter à SCOM un point qui lui manque cruellement : la facilité d’accès, en particulier aux utilisateurs non techniques.

Une supervision ne sert à rien si personne ne se sert des données qui en sont issues, et SquaredUp fournit une réponse pertinente à ce manque flagrant dans le produit de base.

ZABBIX - Script - Liste des items d'un template (Native API)

Le script ci-dessous interroge l'api native zabbix pour récupérer le détail de la liste des items d'un nom de template donné en paramètre.

 

ZabbixGetItemsOfSpecTemplate(Native_API).ps1 (2,29 kb)

 

### Get Items of a specific template name (Use native zabbix json api)
Param(
[Parameter(Mandatory=$false)] $baseurl='https://MyZabbixSrv.My.domain/zabbix',
$credential = (Get-Credential -Credential "MyAccount"),
$TemplateName = "MY_TEMPLATE"
)

$global:JsonParams = @{}
    
# 
Function ConnectZabbix($cred,$baseurl)
{
$JsonParams.body =  @{
        "jsonrpc"= "2.0"
        "method"= "user.login"
        "params"= @{
            "user"= $cred.UserName
            "password"= $cred.GetNetworkCredential().Password
        }
        "id"= 1
        "auth"= $null
    } | ConvertTo-Json
    $JsonParams.uri = "$baseurl/api_jsonrpc.php"
    $JsonParams.headers = @{"Content-Type" = "application/json"}
    $JsonParams.method = "Post"


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

$global:Connresult = Invoke-WebRequest @JsonParams -UseBasicParsing

}

# Invoke ConnectZabbix
ConnectZabbix -cred $credential -baseurl $baseurl



## GET TEMPLATE ID ##
Function GetTemplateId($TemplateName)
{
$JsonParams.body = @{
    "jsonrpc"= "2.0"
    "method"= "template.get"
    "params"= @{
       output = "extend"
        "filter" = @{"host"=$TemplateName}
        }
    auth = ($Connresult.Content | ConvertFrom-Json).result
    id = 2
} | ConvertTo-Json

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

$TemplateId = $result.result | select templateid -ExpandProperty templateid
$TemplateId
}



## GET ITEMS FROM TEMPLATE ID ##
$JsonParams.body = @{
    "jsonrpc"= "2.0"
    "method"= "item.get"
    "params"= @{
        output = "extend"
        templateids = $(GetTemplateId -TemplateName $TemplateName)
        }
    auth = ($Connresult.Content | ConvertFrom-Json).result
    id = 2
} | ConvertTo-Json

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


write-host "`n############################################################################"
write-host "## ZABBIX ITEMS IN $TemplateName ##:"
write-host "#############################################################################`n"


# Display Result tableau
$result.result | ft

 

Activer SSPR sur Azure

Qu'est-ce que SSPR ?

SSPR ou Self-service password reset est une fonctionnalité d'Azure Active Directory permettant aux utilisateurs de réinitialiser eux-même leur mot de passe.

 

Quels sont les avantages de SSPR ?

  • Autonomie des utilisateurs pour réinitialiser leur mot de passe et par conséquent réduction du nombre de sollicitations des IT
  • Les méthodes de récupérations proposées par SSPR sont connus et facile à prendre en main : question secrètes, vérification par SMS etc
  • Les options de configuration de SSPR peuvent être aisément changées
  • L'utilisation de SSPR est loguée et ces logs sont facilement accessible

 

Comment configurer SSPR ?

 

1. Rendez-vous dans portal.azure.com et connectez-vous avec un compte qui possède le rôle Global Administrator

2. Cliquez sur l'icone des triples barres horizontales pour afficher le menu du portail Azure puis cliquer sur Azure Active Directory

3. Dans le menu cliquez sur Password Reset

 

4. Vous arrivez directement dans l'onglet Properties, choisissez si vous voulez que SSPR soit activé pour l'ensemble des utilisateurs All ou pour un nombre restreint Selected

 

5. Cliquez sur Authentication methods et choisissez les paramètres voulus : méthodes de récupération disponible pour les utilisateurs, nombre de méthodes de récupération minimum nécessaire etc

 

6. Cliquez sur l'onglet Registration, vous pouvez forcer l'inscription des utilisateurs à SSPR lors de leur prochaine connexion au portail office. Vous devez également choisir au bout de combien de jours les utilisateurs doivent confirmer leurs informations de méthodes de récupération.

 

7. Vous avez d'autres options de configurations dans les onglets Notifications et Customization. L'onglet On-premises integration est quant à lui utilisé dans les environnements hybrides.

 

Quelle est l'expérience utilisateur lors de l'inscription à SSPR ?

 

1. Si vous n'avez pas obligé l'utilisateur à s'inscrire, vous devez lui fournir ce lien : aka.ms/ssprsetup sinon il aura l'image suivante à sa prochaine connexion

 

2. L'utilisateur devra ensuite confirmer son mot de passe actuel puis sera invité à s'inscrire à SSPR, les méthodes de récupération que vous avez choisi précédemment seront proposées à l'utilisateur. Il peut les configurer en cliquant sur set up now à coté de la méthode de récupération

 

3. Après avoir configuré le nombre minimum de méthodes de récupération, il peut alors cliquer sur looks good pour finir son inscription à SSPR

 

Comment l'utilisateur peut utiliser SSPR pour réinitialiser son mot de passe ?

 

1. L'utilisateur peut soit utiliser le lien suivant : aka.ms/sspr soit se rendre sur portal.office.com et cliquer sur Can't access your account?

 

2. Il lui sera alors demandé d'entrer l'UPN de son compte et de valider un captcha. Il pourra ensuite choisir parmi les méthodes de récupération qu'il a configuré pour réinitialiser son mot de passe

 

3. L'utilisateur sera alors invité à saisir un nouveau mot de passe

 

O365 : Exporter le contenue d'une boite mail dans un pst

Il peut être nécessaire de réaliser la sauvegarde d'une boite mail avant une action ou pour diverses raisons, voici comment réaliser l'opération depuis le portail O365.

 

1 - Connectez vous au portail admin O365 (https://protection.office.com)

2 - Sélectionnez "Permissions"

3 - Puis cochez "eDiscovery Manager"

4 - Et enfin attribuer les droits au compte avec lequel vous souhaitez faire l'export sur les deux rôles suivants:

 

et

 

5 - Déroulez le menu "Search" et sélectionnez "Content Search"

6 - Dans le nouvel onglet sélectionnez "New Search"

7 - Sélectionnez "Specify location" puis cliquez sur "Modify..."

8 - Sélectionnez "Choose users, groups, or teams"

9 - cliquez sur "Choose users, groups, or teams"

 

10 - Entrez au moins les trois premiers caractères de la boite au lettre, puis sélectionnez le compte en cochant la case sur sa gauche et faites "Choose"

11 - Cliquez sur "Done"

12 - Puis sur "Save"

13 - Et enfin "Save & Run"

14 - Donnez un nom à votre recherche puis faites "Save"

15 - Attendez la fin de l'opération

Voila, vous avez réalisez un fichier PST de la boite mail, pour l'exporter il faudra vous rendre sur "Search"

 

16 - Sélectionnez la recherche créée précédemment.

 

17 - Sélectionnez "Export Results"

18 - Choisissez les options qui vous conviennent et cliquez sur "Export"

 

Voilà, votre sauvegarde est maintenant en ligne et prête à être téléchargée.

Si toutes fois vous envisagiez de télécharger le PST, il faudra utiliser Internet Explorer ou Edge (à l'heure ou j'écris ces lignes) et vous rendre dans "Export

Puis sélectionnez votre export et faites "Download Results"

 

Copiez la clé d'export

Collez la clé d'export et indiquez le répertoire de téléchargement, puis faites "Démarrer"

SCOM - Script - Supprimer ou Mettre en mode maintenance un/des agent selon la valeur d'une propriété (Nouvelle version)

Le script suivant est une nouvelle version d'un script récemment proposé. Ont été rajouté le choix entre suppression et mode maintenance (on verifie aussi que la machine est déjà en mode maintenance)

 

DeleteOrMaintenanceAgentUponPropertyValue.ps1 (14,85 kb)

 

## DeleteOrMaintenanceAgentUponPropertyValue.ps1
## SCOM - REMOVE FROM CONSOLE OR PUT IN MAINTENANCE MODE, AGENT(S) THAT HAVE SPECIFIC VALUES IN ONE OR MORE CLASS PROPERTY.
## AUTHOR: C.JOURDAN
## Version: 1.1

##  PARAMETERS
##  $MS: Target Management Server
##  $ObjectClass: Display Name of Target Class
##  $FirstProperty: name of class property
##  $FirstPropVal: multi value possible of $FirstProperty
##  $Action: DELETE or MAINTENANCE
##  $MaintenanceDuration: Nb of minutes for Maintenance Mode
##  $ThreshNotDelete: Nb of found computers to delete over which we only warn (NO AUTOMATIC DELETE)

## NOTES: $ThreshNotDelete PARAMETER IS A SECURITY OPTION TO AVOID DELETION OF TWO MANY AGENTS. BE SURE OF THE APPLIED CRITERIAS BEFORE UNLOCK THAT! 


#PARAMETERS
Param(
[Parameter(Mandatory=$false)]
$MGroup,
[Parameter(Mandatory=$false)]
$MS="MyMS",
[Parameter(Mandatory=$false)]
$ObjectClass="MyClass",
[Parameter(Mandatory=$false)]
$FirstProperty='MyProperty',
[Parameter(Mandatory=$false)]
$FirstPropVal="^.*(AZERTY|QWERTY).*$",
<# -- ADDITIONAL PROPERTIES FROM $ObjectClass INSTANCE -- SEE CLASS INSTANCE RETRIEVE SECTION
[Parameter(Mandatory=$false)]
$SecondProperty='Prop2',
[Parameter(Mandatory=$false)]
$SecondPropVal='Value2'
#>
[Parameter(Mandatory=$false)]
$Action = "Maintenance",
[Parameter(Mandatory=$false)]
$MaintenanceDuration = 30,
[Parameter(Mandatory=$false)]
$ThreshNotDelete = 10
)

#ScriptName
$ScriptName = "DeleteOrMaintenanceAgentUponPropertyValue.ps1"



#FUNCTIONS

# NewEventSource
# Check of a source existance  in the 'operation manager' eventlog that match the script name, to log some events.
         Function NewEventSource 
         { 
         if(!(Test-Path "HKLM:\SYSTEM\CurrentControlSet\services\eventlog\Operations Manager\$ScriptName")) 
         { 
         New-EventLog -LogName "Operations Manager" -Source $ScriptName 
         }
         } 


# DeleteSCOMAgent
# Remove agent from SCOM Console.
Function DeleteSCOMAgent 
{
Param(
  [string[]]$AgentComputerName,
  [string]$MSServer
)

[System.Reflection.Assembly]::Load("Microsoft.EnterpriseManagement.Core, Version=7.0.5000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")
[System.Reflection.Assembly]::Load("Microsoft.EnterpriseManagement.OperationsManager, Version=7.0.5000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")



function New-Collection ( [type] $type ) 
{
	$typeAssemblyName = $type.AssemblyQualifiedName;
	$collection = new-object "System.Collections.ObjectModel.Collection``1[[$typeAssemblyName]]";
	return ,($collection);
}




# Connect to management group
Write-output "Connecting to management group "$ConnectionSetting.name""

$ConnectionSetting = New-Object Microsoft.EnterpriseManagement.ManagementGroup($MSServer)
$admin = $ConnectionSetting.GetAdministration()


Write-output "Getting agent managed computers"
$agentManagedComputers = $admin.GetAllAgentManagedComputers()

# Get list of agents to delete
foreach ($name in $AgentComputerName) 
{
    Write-output "Checking for $name"
    foreach ($agent in $agentManagedComputers)
    {
        if ($deleteCollection -eq $null) 
        {
            $deleteCollection = new-collection $agent.GetType()
        }

        
        if (@($agent.PrincipalName -eq $name))
        {
	    Write-output "Matched $name"
            $deleteCollection.Add($agent)
            break
        }
    }
}

if ($deleteCollection.Count -gt 0) 
{
    Write-output "Deleting agents"
    $admin.DeleteAgentManagedComputers($deleteCollection)
    if($?){
           $Script:result="Agents deleted"
           Write-Output $result
          }
    Else  {
           $result="Error during deletion of one ore more agent"
           Write-Output $result
          }
}

Else
    {
    $result="No Agent found to delete"
    Write-Output $result
    }


}


Function SetMM
{
# Function SetMM 
########################################################################
# 
#
[CmdletBinding()]

param(
  [string]$HostToMM,
  [string]$Duration
)

$startTime = [DateTime]::Now
$endTime = $startTime.AddMinutes($Duration)

    # Get "Microsoft.Windows.Computer" Class
    $Class = get-SCOMclass | where-object {$_.Name -eq "Microsoft.Windows.Computer"};

    $Instance = Get-SCOMClassInstance -Class $Class | Where-Object {$_.Displayname -like "$HostToMM*"};
    
    Start-SCOMMaintenanceMode -Instance $Instance -Reason "PlannedOther" -EndTime $endTime -Comment "PLANNED BY SCOM AGENT REMOVER" -ErrorAction Stop
    
    
}



#END FUNCTIONS



#Log of script execution 
NewEventSource
$message =  "Execution du script $ScriptName"
$message
write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 999 -Message $message -EntryType Information 


# Check if $Action is valid
if ($Action -notmatch "^delete|maintenance$")
    {
    $message = "NO VALID ACTION HAS BEEN CHOOSED - POSSIBLE VALUE: `"DELETE`" OR `"MAINTENANCE`""
    write-host -ForegroundColor Yellow $message
    NewEventSource 
    write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1000 -Message $message -EntryType Warning
    exit 1
    }



#Import of SCOM Powershell module
try
{
Import-Module -Name OperationsManager -ErrorAction stop
}
catch
{
$message = "ERROR DURING IMPORT OF SCOM PS MODULE"
write-host -ForegroundColor red $message
NewEventSource 
write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1001 -Message $message -EntryType Error 
exit 1 
}



#Connection to management group $MGroup
try
{
New-SCOMManagementGroupConnection -ComputerName $MS
}
catch
{
$message = "ERROR DURING CONNECTION TO $MS"
write-host -ForegroundColor red $message
NewEventSource 
write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1002 -Message $message -EntryType Error 
exit 1 
}


# Get $ObjectClass Class
$Class = Get-SCOMClass -displayname $ObjectClass | Where-Object {$_.PropertyCollection -match "^.*($FirstProperty|$SecondProperty).*$"} -ErrorAction stop    ## -- WE CHECK THAT THE TARGET CLASS REALLY HOLD THE WANTED PROPERTIES
if (!($Class))
{
$message = "ERROR DURING RETRIEVE OF '$ObjectClass' CLASS. (CRITERIAS: Class=`"$ObjectClass`" - Property=`"$FirstProperty`" - Value=`"$FirstPropVal`")"
write-host -ForegroundColor red $message
NewEventSource 
write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1003 -Message $message -EntryType Error 
exit 1 
}




# Get Computers that have $FirstProperty value as: $FirstPropVal 
try
{
$TargetComp = $Class | Get-SCOMClassInstance | Where-Object {
$_."[$($Class.Name)].$FirstProperty".value -match $FirstPropVal -OR $_.$FirstProperty -match $FirstPropVal`               ##-- DIFFERENT COMBINATION (THE "[$($Class.Name)]" SYNTAX IS TO INCLUDE CASE OF A NOTE PROPERTY
#-AND $_."[$($Class.Name)].$SecondProperty".value -eq $SecondPropVal -OR $_.$SecondProperty -eq $SecondPropVal`     ##-- ADDITIONAL POTENTIAL PROPERTIES (SEE SCRIPT PARAMS)
} -ErrorAction Stop

#$TargetComp = $Class | Get-SCOMClassInstance | Where-Object {                                                       ## -- TO TEST UNFOUND COMPUTER SCENARIO
#$_."[$($Class.Name)].$FirstProperty".value -eq "azerty" -OR $_.$FirstProperty -eq "azerty"`                        ## -- TO TEST UNFOUND COMPUTER SCENARIO
#} -ErrorAction Stop                                                                                                ## -- TO TEST UNFOUND COMPUTER SCENARIO

}
catch
{
$message = "ERROR DURING RETRIEVE OF CLASS INSTANCES (CRITERIAS: Class=`"$ObjectClass`" - Property=`"$FirstProperty`" - Value=`"$FirstPropVal`")"
write-host -ForegroundColor red $message
NewEventSource 
write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1004 -Message $message -EntryType Error 
exit 1 
}




switch($Action)
{
"Delete" {


# Analyse the content of $TargetComp
switch($TargetComp.Count)
{
{$_ -lt 1}                  {            
                            $message = "NO AGENT TO REMOVE (CRITERIAS: Class=`"$ObjectClass`" - Property=`"$FirstProperty`" - Value=`"$FirstPropVal`")"
                            Write-Host -F Blue -B White $message
                            NewEventSource 
                            write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1005 -Message $message -EntryType Information 
                            }


{$_ -ge 1 -AND $_ -le $ThreshNotDelete} ## -- SECURITY OPTION TO AVOID DELETION OF TWO MANY AGENTS. BE SURE OF THE APPLIED CRITERIAS BEFORE UNLOCK THAT!
                            {
                            $message = "FOLLOWING AGENTS WILL BE REMOVED:"
                            Write-Host -F Yellow $message
                            $TargetComp.displayname
                                                            
                                DeleteSCOMAgent -AgentComputerName $TargetComp.displayname -MSServer $MS
                                #$result
                                switch($result)
                                    {
                                    "Agents deleted" 
                                                                                        {
                                                                                            $message = "FOLLOWING AGENTS HAS BEEN REMOVED FROM SCOM CONSOLE (CRITERIAS: Class=`"$ObjectClass`" - Property=`"$FirstProperty`" - Value=`"$FirstPropVal`") :`n "
                                                                                            $message += $TargetComp | foreach {$_.DisplayName ;"`n"}
                                                                                            write-host $message
                                                                                            NewEventSource 
                                                                                            write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1006 -Message $message -EntryType Information 
                                                                                        }
                                    
                                    "Error during deletion of one ore more agent" 
                                                                                        {
                                                                                            $message = "ERROR DURING DELETION OF ONE OR MORE AGENT! MANUAL CHECK REQUIRED (CRITERIAS: Class=`"$ObjectClass`" - Property=`"$FirstProperty`" - Value=`"$FirstPropVal`") "
                                                                                            write-host $message
                                                                                            NewEventSource 
                                                                                            write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1007 -Message $message -EntryType Warning
                                                                                        } 

                                    "No Agent found to delete" 
                                                                                        {
                                                                                            $message = "NO AGENT FOUND TO DELETE - MANUAL CHECK REQUIRED (CRITERIAS: Class=`"$ObjectClass`" - Property=`"$FirstProperty`" - Value=`"$FirstPropVal`")"
                                                                                            write-host $message
                                                                                            NewEventSource 
                                                                                            write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1008 -Message $message -EntryType Warning
                                                                                        } 


                                    
                                
                                    
                                
                            
                                }

                            }

{$_ -gt $ThreshNotDelete}                 {
                            $message = "WARNING: NUMBER OF AGENTS TO REMOVE IS GREATER THAN 10 ! MANUAL CHECK REQUIRED"  ## -- SECURITY OPTION TO AVOID DELETION OF TWO MANY AGENTS. BE SURE OF THE APPLIED CRITERIAS BEFORE UNLOCK THAT!
                            Write-Host -F red $message
                            $TargetComp.displayname
                            NewEventSource 
                            write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1009 -Message $message -EntryType Warning
                            }


}


         }


"Maintenance" {

#Clear-Variable message

    If ($TargetComp.Count -ge 1)
        {

        foreach ($target in $TargetComp)
            {
            If (Get-SCOMMaintenanceMode -Instance $target)
                {
                #$message += "`n$target IS ALREADY IN MAINTENANCE MODE"
                $AlreadyInMM += "$target`n"
                }
            Else
                {
                SetMM -HostToMM $target -Duration $MaintenanceDuration
                $PutInMM += "$target`n" 
                }
            }
                       

            $message = "`nFOLLOWING AGENTS HAS BEEN SET IN MAINTENANCE MODE (CRITERIAS: Class=`"$ObjectClass`" - Property=`"$FirstProperty`" - Value=`"$FirstPropVal`") :`n"
            $message += $PutInMM
            $message += "`n`nFOLLOWING AGENTS ARE ALREADY IN MAINTENANCE MODE (CRITERIAS: Class=`"$ObjectClass`" - Property=`"$FirstProperty`" - Value=`"$FirstPropVal`") :`n"
            $message += $AlreadyInMM
            write-host $message
            NewEventSource 
            write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1010 -Message $message -EntryType Information 
         }
        
    Else
        {
        $message = "NO AGENT TO PUT IN MAINTENANCE MODE HAS BEEN FOUND. (CRITERIAS: Class=`"$ObjectClass`" - Property=`"$FirstProperty`" - Value=`"$FirstPropVal`")"
        write-host $message
        NewEventSource 
        write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1011 -Message $message -EntryType Information
        }
    }


default {

        $message = "No action has been choosed. Possible value: `"Delete`" (Delete Agent from console) or `"Maintenance`" (Put corresponding computer in Maintenance Mode)"
        write-host -ForegroundColor red $message
        NewEventSource 
        write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1012 -Message $message -EntryType Error 
        exit 1 
        }

}