PI Services

Le blog des collaborateurs de PI Services

SCOM – Script Mode Maintenance des Health Service Watcher

Lors du basculement d’agents gérés par une gateway vers une gateway de secours (failover), il peut arriver que quelques alertes “Heartbeat Failure” indésirables soit générées.

Le script suivant propose de lister, démarrer  ou arrêter les modes maintenance des instances Health Service Watcher des agents gérés par une gateway/management server donné.

Cette action est bien entendu possible pour une autre classe, dans la mesure ou le DisplayName  de l’instance correspond a celui de l’agent.

 

 

########################################################################################################################################### ## SCRIPT TO START/STOP/DISPLAY MAINTENANCE MODE FOR HEALTH SERVICE WATCHER OBJECTS THAT DEPENDS FROM SPECIFIC MANAGEMENT SERVER OR GATEWAY ## Author: CJOURDAN ########################################################################################################################################### #Parameters # $MGroup : Management Group to connect to # $MStoConnect : Management server to connect to # $PrimMS : Management server or Gateway FQDN from which depend agents. # $Reason : Reason for Maintenance Mode (Valid Reason are: PlannedOther # UnPlannedOther # PlannedHardwareMaintenance # UnplannedHardwareMaintenance # PlannedHardwareInstallation # UnplannedHardwareInstallation # PlannedOperatingSystemReconfiguration # UnplannedOperatingSystemReconfiguration # PlannedApplicationMaintenance # ApplicationInstallation # ApplicationUnresponsive # ApplicationUnstable # SecurityIssue # LossOfNetworkConnectivity) # # $Comment : Comment for Maintenance Mode # $MMAction : START or STOP OR DISPLAY Maintenance Mode # $MMDuration : Maintenance Mode Duration in minutes (only valuable for START $MMAction) # EXAMPLES: # Display Health Service Watcher Maintenance Mode Status for agents primary managed by MyPriMaryMS.mydomain.home # .\ScomSwitchMM.ps1 -MGroup MyMGROUP -MStoConnect MyMS.mydomain.home -PrimMS MyPriMaryMS.mydomain.home -MMAction display # Start Health Service Watcher Maintenance Mode for agents primary managed by MyPriMaryMS.mydomain.home during 60 min # .\ScomSwitchMM.ps1 -MGroup MyMGROUP -MStoConnect MyMS.mydomain.home -PrimMS MyPriMaryMS.mydomain.home -MMAction start -MMDuration 60 Param( [Parameter(Mandatory=$false)] $ClassName = "Health Service Watcher", [Parameter(Mandatory=$false)] $MGroup = "MyMGROUP", [Parameter(Mandatory=$false)] $MStoConnect= "MyMS.mydomain.home", [Parameter(Mandatory=$true)] $PrimMS= "MyPriMaryMS.mydomain.home", [Parameter(Mandatory=$false)] $Reason = "PlannedOther", [Parameter(Mandatory=$false)] $Comment = "", [Parameter(Mandatory=$true)] $MMAction = $(Read-Host -Prompt "PROVIDE TYPE OF MAINTENANCE MODE ACTION: START or STOP OR DISPLAY"), [Parameter(Mandatory=$false)] # $MMDuration in minutes $MMDuration = 0 ) if ($MMAction -notmatch ".*STOP.*|.*START.*|.*DISPLAY.*") { write-host -ForegroundColor Yellow "YOU MUST PROVIDE VALID MAINTENANCE MODE ACTION TYPE: START or STOP or DISPLAY" EXIT 1 } $cred = $(Get-Credential -Credential "MyDomain\") #Import du module SCOM try { Import-Module -Name OperationsManager -ErrorAction stop } catch { write-host -ForegroundColor red "Error during import of SCOM PS Module" EXIT 1 } #Connection au management group $MGroup try { New-SCOMManagementGroupConnection -ComputerName $MStoConnect -Credential $cred } catch { write-host -ForegroundColor red "Error during connection to MS $MStoConnect - CHECK CREDENTIALS USED" EXIT 1 } # Get Scom agents that have $PrimMS as Primary Management Server $agents = get-scomagent | where {$_.PrimaryManagementServerName -eq $PrimMS} if (!($agents)) { write-host "NO SCOM AGENTS FOUND FOR SERVER $PrimMS - CHECK THAT THE NAME IS CORRECT (YOU MUST PROVIDE FQDN) OR THAT THIS SERVER BELONG TO $MGroup MANAGEMENT GROUP" EXIT 1 } # Get "Health Service Watcher" Class Instances $class = Get-SCOMClass -DisplayName $ClassName switch($MMAction) { START { # Get instances of "Health Service Watcher" Class $ClassInstances = Get-SCOMClassInstance -Class $class # Class to put in MM Table $ClassInstToMM = @() # Get class instances that match agents foreach ($agent in $agents) { $ClassInstToMM += ($ClassInstances | Where-Object {$_.DisplayName -eq $agent.displayname}) } $starttime = $(get-date).ToUniversalTime() $endtime = $(get-date).AddMinutes($MMDuration).ToUniversalTime() # PUT IN Maintenance Mode $($ClassInstToMM | foreach {$_.schedulemaintenancemode($starttime,$endtime,$Reason,$Comment)}) # Display effective instances in MM write-host "EFFECTIVE INSTANCES OF CLASS '$ClassName' IN MAINTENANCE MODE (Primary Managed by $PrimMS):" # Get instances of "Health Service Watcher" Class $ClassInstances = Get-SCOMClassInstance -Class $class $ClassInstInMM = @() # Get class instances that match agents foreach ($agent in $agents) { $ClassInstInMM += ($ClassInstances | Where-Object {$_.DisplayName -eq $agent.displayname}) } $ClassInstInMM } STOP { # Get instances of "Health Service Watcher" Class $ClassInstances = Get-SCOMClassInstance -Class $class # Class to put out of MM Table $ClassInstOoMM = @() # Get class instances that match agents foreach ($agent in $agents) { $ClassInstOoMM += ($ClassInstances | Where-Object {$_.DisplayName -eq $agent.displayname}) } # Only Endttime in necessary and it is now $endtime = $(get-date).ToUniversalTime() # PUT IN Maintenance Mode $($ClassInstOoMM | foreach {$_.stopmaintenancemode($endtime)}) # Display effective instances in MM write-host "EFFECTIVE INSTANCES OF CLASS '$ClassName' OUT OF MAINTENANCE MODE (Primary Managed by $PrimMS):" # Get instances of "Health Service Watcher" Class $ClassInstances = Get-SCOMClassInstance -Class $class $ClassInstOoMM = @() # Get class instances that match agents foreach ($agent in $agents) { $ClassInstOoMM += ($ClassInstances | Where-Object {$_.DisplayName -eq $agent.displayname}) } $ClassInstOoMM } DISPLAY { # Display effective instances in MM write-host "`n INSTANCES OF CLASS '$ClassName' MAINTENANCE MODE STATE (Primary Managed by $PrimMS):" # Get instances of "Health Service Watcher" Class $ClassInstances = Get-SCOMClassInstance -Class $class $ClassInstMM = @() # Get class instances that match agents foreach ($agent in $agents) { $ClassInstMM += ($ClassInstances | Where-Object {$_.DisplayName -eq $agent.displayname}) } $ClassInstMM } }

SCOM – SQL – Requête d’inventaire des overrides

La requête ci-dessous permet de lister tout les overrides de manière ‘clarifiés’ afin d’identifier les objets a la source de ces overrides, les paramètres concernés et les management pack sources et de destination.

Les paramètres @Startdate et @EndDate permettent de spécifier une fenêtre de temps concernant les dates de création et de dernière modification des overrides.

 

 

declare @StartDate  datetime declare @EndDate    datetime set @EndDate = GETDATE() set @StartDate = DATEADD(day,-60,@EndDate)   SELECT DISTINCT MP.MPFriendlyName AS 'Management Pack' , aov.ParentType AS 'Type' ,(CASE        WHEN AOV.OverrideType = 'RuleProperty' THEN R.RuleName        WHEN AOV.OverrideType = 'MonitorProperty' THEN M.MonitorName        WHEN AOV.OverrideType = 'RuleConfiguration' THEN R.RuleName        WHEN AOV.OverrideType = 'MonitorConfiguration' THEN M.MonitorName  END) AS 'NameType', mt.DisplayName AS ContextDisplayName , aov.OverrideableParameterName , aov.Value, (CASE Enforced        WHEN '0' THEN 'False'        WHEN '1' THEN 'True'   END) AS 'Enforced'   , aov.LastModified   , aov.TimeAdded   ,(CASE   WHEN AOV.OverrideType = 'RuleProperty' THEN              (CASE R.RuleEnabled              WHEN '0' THEN 'False'              WHEN '2' THEN 'True'              WHEN '3' THEN 'True'              WHEN '4' THEN 'True'              END)     WHEN AOV.OverrideType = 'MonitorProperty' THEN              (CASE M.MonitorEnabled              WHEN '0' THEN 'False'              WHEN '2' THEN 'True'              WHEN '3' THEN 'True'              WHEN '4' THEN 'True'              END)     WHEN AOV.OverrideType = 'RuleConfiguration' THEN              (CASE R.RuleEnabled              WHEN '0' THEN 'False'              WHEN '2' THEN 'True'              WHEN '3' THEN 'True'              WHEN '4' THEN 'True'              END)                WHEN AOV.OverrideType = 'MonitorConfiguration' THEN              (CASE M.MonitorEnabled              WHEN '0' THEN 'False'              WHEN '2' THEN 'True'              WHEN '3' THEN 'True'              WHEN '4' THEN 'True'              END) END) AS 'Enable_by_default', MPSTORE.MPFriendlyName AS 'MP Stored'   FROM AllOverrideView AS aov LEFT OUTER JOIN Rules AS R WITH (nolock) ON aov.TargetId = R.RuleId AND (aov.OverrideType = 'RuleProperty' OR aov.OverrideType = 'RuleConfiguration') LEFT OUTER JOIN Monitor AS M WITH (nolock) ON aov.TargetId = M.MonitorId AND (aov.OverrideType = 'MonitorProperty' OR aov.OverrideType = 'MonitorConfiguration') LEFT OUTER JOIN  ManagementPack AS MP WITH (nolock) ON (CASE                                                                                               WHEN AOV.OverrideType = 'RuleProperty' THEN R.ManagementPackId                                                                                               WHEN AOV.OverrideType = 'RuleConfiguration' THEN R.ManagementPackId                                                                                               WHEN AOV.OverrideType = 'MonitorProperty' THEN M.ManagementPackId                                                                                               WHEN AOV.OverrideType = 'MonitorConfiguration' THEN M.ManagementPackId                                                                                               END) = MP.ManagementPackId INNER JOIN ManagementPack AS MPSTORE WITH (nolock) ON MPSTORE.ManagementPackId = aov.ManagementPackId LEFT OUTER JOIN ManagedTypeView AS mt WITH (nolock) ON mt.Id = aov.ContextId LEFT OUTER JOIN ManagedTypeView AS mtv WITH (nolock) ON mtv.Id = aov.ContextObjectId   WHERE (MP.MPFriendlyName IS NOT NULL) AND (aov.LastModified BETWEEN @StartDate AND @EndDate) OR (MP.MPFriendlyName IS NOT NULL) AND (aov.TimeAdded BETWEEN @StartDate AND @EndDate)   ORDER BY aov.TimeAdded DESC

Utilisation de WinSCP .Net Assembly et COM library

Dans cet article nous allons apprendre l'utilisation et l'importance de WinSCP .Net Assembly et COM library.

Introduction

Nous sommes habitué à utiliser le client WinSCP pour se connecter sur un serveur SFTP,SCP ou FTP. Il existe même un module très basique appelé WinSCP.com pour envoyer ou réceptionner des données via un fichier *.bat. Cependant, beaucoup d'entre nous ignore l'existance de WinSCP .Net Assembly et COM library qui offre la possibilité de manipuler des fichiers à distance depuis un environnement supportant .NET, par exemple C#,VB. Net, PowerShell,SSIS et même depuis les sites MS AZURE.

WinSCP .Net assembly et COM library offrent beaucoup de possibilité en termes de ligne de commandes pour automatiser l'envoi et la réception de fichier depuis un serveur FTP,SCP ou sFTP. 

Prérequis

Télécharger le fichier zip indiqué ci-dessous et décompresser le.

Exemple de programmation en PoSH

  • L'initialisation d'une connexion sur un serveur
try
{
    # appel WinSCP .NET assembly
    Add-Type -Path "WinSCPnet.dll"
 
    # paramètre de connexion
    $sessionOptions = New-Object WinSCP.SessionOptions -Property @{
        Protocol = [WinSCP.Protocol]::Sftp
        HostName = "example.com"
        UserName = "user"
        Password = "mypassword"
        SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"
    }
 
    $session = New-Object WinSCP.Session
 
    try
    {
        # initialiser la connexion
        $session.Open($sessionOptions)
 
        Write-Host "You are now connected!!!"
    }
    finally
    {
        # Déconnecter et nettoyer
        $session.Dispose()
    }
 
    exit 0
}
catch [Exception]
{
    # Exception
    Write-Host ("Error: {0}" -f $_.Exception.Message)
    exit 1
}

Pour se connecter sur un serveur sFTP avec une clé privée et sans login et mot de passe, remplacer la ligne :

Password = "mypassword"
        SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"

par 

SshPrivateKeyPath = "chemin vers la clé privée"
        GiveUpSecurityAndAcceptAnySshHostKey = "true"
  • Télécharger un fichier 

Pour télécharger un fichier avec son nom, utiliser la ligne de commande ci-dessous:

$session.GetFiles($session.EscapeFileMask(<chemin complet du fichier>), <destination locale>).Check()
  • Pour uploader un fichier 
 # Upload files
        $transferOptions = New-Object WinSCP.TransferOptions
        $transferOptions.TransferMode = [WinSCP.TransferMode]::Binary
 
        $transferResult = $session.PutFiles("d:\toupload\*", "/home/user/", $False, $transferOptions)

 

Pour avoir plus d'informations sur les classes existantes : https://winscp.net/eng/docs/library

 

Quest RUM : Script de désinstallation des agents

Bonjour à tous !

Lors d'une migration effectuée à l'aide du produit Quest Migration Manager for Active Directory, vous vous retrouvez souvent en fin de migration avec un nombre conséquent d'agents Quest à désinstaller de tous les postes migrés.

Ce que vous pouvez très bien faire à l'aide de Quest RUM (Resource Updating Manager) via l'option Cleanup :

Mais il peut arriver qu'entre temps que certains postes migrés soient devenus indisponibles. Plutôt que de refaire une passe numéro X pour désinstaller les agents, nous allons voir comment automatiser la désinstallation de ceux-ci.

Prérequis

Pour ce faire, il vous faut :

  • Un serveur sur lequel sera placé un partage accessible par toutes les machines ayant un agent Quest
  • Un éditeur de script Powershell
  • Une console d'édition de stratégies de groupe

Le partage de fichiers

Afin que notre script de désinstallation puisse écrire les logs nécessaire, il doit avoir à disposition un partage sur lequel les machines concernées puissent avoir un droit d'écriture de fichiers.

Par défaut, le script va utiliser le nom de partage QuestUninstallLogs$ mais vous pourrez le modifier via les arguments du script. Nous rajoutons un à la fin du nom du partage afin de masquer celui-ci.

Il faut ajouter sur le partage (droit de partage) le droit en modification pour le groupe Everyone.

Il faut ajouter sur le dossier (droit NTFS) le droit en modification et en écriture pour le groupe Authenticated Users

Une fois cela fait, nous pouvons passer à l'édition du script.

Le script

Arguments

Le script s'appelle à l'aide des arguments suivants :

  • -Pole (obligatoire) : Nom du dossier de 1er niveau des logs
  • -Site (obligatoire) : Nom du dossier de 2ème niveau des logs
  • -LogServer (obligatoire) : Nom du serveur devant recevoir les logs
  • -LogShare (facultatif) : Nom du partage devant recevoir les logs

Sortie

Deux types de fichiers de logs vont être générés en sortie dans le chemin indiqué en paramètre du script :

  • XXX_SUMMARY.log : Fichier résumant toutes les désinstallations effectuées par le script
  • COMPUTERS\PC-XXX.log : Fichier détaillant le déroulement de la désinstallation de l'agent Quest pour le poste concerné

Code

#-------------------#
# Script Parameters #
#-------------------#
# Description
# The Uninstall_Quest_Agent script is uninstalling the Quest RUM Agent
# 
# How to use it 
#
# .\Uninstall_Quest_Agent.ps1 -Pole "POLE_IDF" -Site "Site_1" -LogServer "LOG_SERVER_1" -LogShare "QuestUninstallLogs$"
#
# -Pole = Targeted Pole
# -Site = Targeted Site
# -LogServer = Server on which the uninstall logs will be stored
# -LogShare (not mandatory) = Network Share on which the uninstall logs will be stored

########## PARAMETERS ##########

[CmdletBinding(DefaultParametersetName="Common")]
param(
	
	#Attribute field to check
	[Parameter(Mandatory=$true,Position=1)][string] $Pole = $null,
	
	#Attribute field to check
	[Parameter(Mandatory=$true,Position=2)][string] $Site = $null,
	
	#Attributes fields to check
	[Parameter(Mandatory=$false,Position=3)][string] $LogServer = $null,

	#Attributes fields to check
	[Parameter(Mandatory=$false,Position=4)][string] $LogShare = "QuestUninstallLogs$"
	
	)

########## SCRIPT EXECUTION ##########

# Check if script has been executed (log file already exists)

# Define logfile path and name
# Detailed logs
$LogFileDirectoryPath = "\\" + $LogServer + "\" + $LogShare + "\" + $Pole + "\" + $Site + "\COMPUTERS"
$LogFileName = $env:computername + ".log"
$LogFilePath = $LogFileDirectoryPath + "\" + $LogFileName

# Summary logs
$SummaryLogFileDirectoryPath = "\\" + $LogServer + "\" + $LogShare + "\" + $Pole + "\" + $Site
$SummaryLogFileName = $Pole + "_" + $Site + "_" + "SUMMARY.log"
$SummaryLogFilePath = $SummaryLogFileDirectoryPath + "\" + $SummaryLogFileName

# End script if Quest Agent Service is missing
$Service = Get-Service QsRUMAgent -ErrorAction SilentlyContinue

if($Service -eq $null)
{
    Exit
}

########## LOG FILES MANAGMENT ##########

# Checking if directories need to be created

# Check if pole directory exists
$PoleFilePath = "\\" + $LogServer + "\" + $LogShare + "\" + $Pole

# If directory don't exist, we create it
if(!(Test-Path $PoleFilePath))
{
    New-Item $PoleFilePath -ItemType Directory
}

# Check if site directory exists
$SiteFilePath = "\\" + $LogServer + "\" + $LogShare + "\" + $Pole + "\" + $Site

# If directory don't exist, we create it
if(!(Test-Path $SiteFilePath))
{
    New-Item $SiteFilePath -ItemType Directory
}

# Check if COMPUTERS directory exists
$ComputersFilePath = "\\" + $LogServer + "\" + $LogShare + "\" + $Pole + "\" + $Site + "\COMPUTERS"

# If directory don't exist, we create it
if(!(Test-Path $ComputersFilePath))
{
    New-Item $ComputersFilePath -ItemType Directory
}

########## UNINSTALLING AGENT ##########

$Date = (Get-Date).ToString()
$ComputerName = "\\" + $env:computername

# Log
$ToWrite = $Date + " - " + "Begining of Quest agent uninstallation"
Add-Content $LogFilePath $ToWrite

# Stopping and Deleting Quest Migration Manager RUM Agent Service
$Service = Get-Service QsRUMAgent -ErrorAction SilentlyContinue

#If service exists
if($Service)
{
    Stop-Service $Service.Name
    # Log
    $ToWrite = $Date + " - " + "Quest Migration Manager RUM Agent Service - Stopped"
    Add-Content $LogFilePath $ToWrite

    sc.exe $ComputerName delete $Service.Name
    # Log
    $ToWrite = $Date + " - " + "Quest Migration Manager RUM Agent Service - Deleted"
    Add-Content $LogFilePath $ToWrite

    # Log Général
    $ToWrite = $Date + " - " + $env:computername + " - " + "Agent Deleted"
    Add-Content $SummaryLogFilePath $ToWrite
}

else
{
    # Log
    $ToWrite = $Date + " - " + "ERROR : Quest Migration Manager RUM Agent Service not found !"
    Add-Content $LogFilePath $ToWrite
}

# Deleting Quest Migration Manager RUM Agent Directory
$QuestAgentDirectory = "$env:SystemRoot\Quest Resource Updating Agent"

#If directory exists
if(Test-Path $QuestAgentDirectory)
{
    Remove-Item $QuestAgentDirectory -Recurse
    # Log
    $ToWrite = $Date + " - " + "Quest Migration Manager RUM Agent Directory - Deleted"
    Add-Content $LogFilePath $ToWrite
}

else
{
    # Log
    $ToWrite = $Date + " - " + "ERROR : Quest Migration Manager RUM Agent Directory not found !"
    Add-Content $LogFilePath $ToWrite
}

# Log
$ToWrite = $Date + " - " + "End of Quest agent uninstallation"
Add-Content $LogFilePath $ToWrite

Utilisation du script

Vous pouvez utiliser ce script directement sur le poste concerné ou par GPO pour une désinstallation groupée.

Par GPO, le script s'utilise dans la section Powershell dans les Paramètres Ordinateurs de la console de configuration des GPO.

Le chemin pour y accéder est Configuration Ordinateur > Stratégies > Paramètres Windows > Arrêt > Scripts Powershell

A minima, le script doit s'appeller à l'aide des paramètres suivants :

Au fur et à mesure que le script est exécuté, vous devriez voir le dossier des logs se remplir, que ce soit pour le log SUMMARY qui résume toutes les désinstallations ou pour les logs individuels par machine.

HPOneView – Script Powershell

Le script ci-dessous utilise le module powershell pour HP OneView afin de requêter des alertes sur les appliances HP OneView avec la possibilité de changer leur état en Cleared.

Pour rappel, HP OneView est l’outil de management et de centralisation de la configuration des des systèmes convergés HP. Il utilise des appliances dédiés a la gestion des materiels.

Au passage, Un management pack HP OneView pour SCOM est fourni afin de superviser les appliances et les materiels gérés.

En surcouche des API REST fourni par HP, il existe un projet d’API pour Powershell et Python permettant de manipuler plus facilement les fonctionnalités de l’interface OneView.

Le site pour l’API Powershell est disponible via https://github.com/HewlettPackard/POSH-HPOneView

Le script est un exemple de connexion et de récupération multi-critère.

 

############################################################################## # SCRIPT DE RECUPERATION DES ALERTES D'UNE APPLIANCE HPONEVIEW ET MISE EN ETAT CLEARED # author: cjourdan # PARAMETRES: # $ApplianceName: Nom de l'appliance # $RessourceName: Nom de la ressource (Server,Enclosure ...). # $DomainName: Domaine AD. # $AlertSeverity: Critical, Warning, OK, Unknown, Disabled # $AlertState: Active, Locked, Cleared, Pending, Running, Completed, Interrupted, Error, Warning, Terminated, Killed. # $DescInclude: Chaine de caractère dans la champ Description a inclure dans la recherche. # $DescExclude: Chaine de caractère dans la champ Description a exclure de la recherche. # $DayOffset = Recuperer les alertes plus recente que J-DayOffset. # Apres Recuperation des alertes, le script demande validation pour mettre les alertes en état Cleared Param( [Parameter(Mandatory=$false)] $ApplianceName = "MyAppliance", [Parameter(Mandatory=$false)] # Server,Enclosure ... $RessourceName = "MyResource", [Parameter(Mandatory=$false)] $DomainName = "MyDomain", [Parameter(Mandatory=$false)] $AlertSeverity = "Critical", [Parameter(Mandatory=$false)] $AlertState = "Cleared", $DescInclude = "*", $DescExclude = "azerty", $DayOffset = 2 ) $user = Read-Host -Prompt "Enter MyDomain Credential without Domain" $passwd = Read-Host -Prompt "Password" -AsSecureString if (-not (get-module HPOneview.200)) { Import-Module HPOneView.200 } # Connexion a l'appliance OneView if (-not($global:ConnectedSessions)) { Connect-HPOVMgmt -Hostname $ApplianceName -UserName $user -Password $passwd -AuthLoginDomain $DomainName } write-host -BackgroundColor White -ForegroundColor Blue "APPLIANCE ONEVIEW: $ApplianceName"`n # NB: Preciser au minimum un filtre de recherche avant le '|' afin de reduire le temps de recuperation des alertes Try { $Alerts = Get-HPOVAlert -ApplianceConnection $ApplianceName -Severity $AlertSeverity | Where-Object {$_.AlertState -eq $AlertState ` -AND $_.associatedresource -like "*$RessourceName*" ` -AND $_.description -like "*$DescInclude*" ` -AND $_.description -notlike "*$DescExclude*"` -AND $([datetime]$_.created) -gt $(get-date).AddDays(-$DayOffset) } $FormAlerts = foreach ($alert in $Alerts) { Write-output "DESCRIPTION: "$alert.description"" ; Write-Output "SEVERITY: "$alert.severity"" ; Write-Output "STATE: "$alert.alertState"" ; Write-Output "CREATED: "(get-date -format G $alert.Created)"" ; Write-Output "CLEARED: "(get-date -format G $alert.clearedtime)"" ; Write-Output "RESSOURCE_NAME: "$alert.associatedresource.resourcename"" ; Write-Output "APPLIANCE: "$alert.ApplianceConnection.Name"" ; Write-Output "" ; Write-Output "*******************" ; Write-Output "" } write-host -BackgroundColor White -ForegroundColor Blue "CRITERES DE RECHERCHE: Resource: $RessourceName / Severity: $AlertSeverity / Status: $AlertState / a inclure: $DescInclude / a exclure: $DescExclude / Plus recentes que: J-$DayOffset"`n $count=$Alerts | Measure-Object | select count -ExpandProperty count write-host -BackgroundColor White -ForegroundColor Blue "NOMBRE D ALERTES: $count" `n $FormAlerts } Catch { Write-Error -ErrorRecord $_ -ErrorAction Stop } $answer = Read-Host -Prompt "VOULEZ VOUS MODIFIER L'ETAT DES CES ALERTES EN ETAT 'CLEARED' ?: Y/N" switch($answer) { "Y" {"MISE EN ETAT CLEARED"} "N" {"AUCUNE ACTION" ; exit} default {"MAUVAISE REPONSE - AUCUNE ACTION" ; exit} } # Clear Alerts Try { $updatedAlert = $Alerts | set-HPOVAlert -Cleared } Catch { Write-Error -ErrorRecord $_ -ErrorAction Stop } $updatedAlert Write-Host -ForegroundColor Green "MISE EN ETAT CLEARED TERMINEE SANS ERREUR !"

SCOM – Script Rapport Etat des instances d’une liste de classe (Sortie Cmdline)

Le script ci-dessous génère un rapport formaté dans la ligne de commande, de l’état des instances d’une liste de classe.

#SCOM - SCRIPT DE REQUETE D'ETAT DES OBJETS D'UNE LISTE DE CLASSE #Variables $MGroup = "MyGroup" $MS= "MyMS" $cred = Get-Credential "MyDomain\" #Liste de classe a recuperer $ClassList = ('SQL DB Engine','SQL Database','SQL DB File','SQL Agent','SQL Reporting Services','SQL Analysis Services') #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 #Recuperation des classes $MonitoringClasses = $ClassList | foreach {Get-SCOMClass -DisplayName $_} if ($MonitoringClasses -eq $null) { write-host "ERROR - UNABLE TO RETRIEVE CLASSES" -ForegroundColor red } write-host "#################################################### `n" write-host "SCOM Management Group: $MGroup `n" write-host "#################################################### `n`n" #Recuperation des instances de chaque classe foreach ($class in $MonitoringClasses) { $MonitoringObjects = $class | Get-SCOMClassInstance -erroraction silentlycontinue | Sort-Object -Descending -Property HealthState write-host -BackgroundColor white -ForegroundColor blue " **************************************************************** `n" write-host -BackgroundColor white -ForegroundColor blue " *** OBJETS DE LA CLASSE "$class.displayname" `n" write-host -BackgroundColor white -ForegroundColor blue " **************************************************************** `n`n" write-host " --- $(get-date -Format F) --- `n`n" write-host " NUMBER OF OBJECT: $($MonitoringObjects | measure-object | select-object -property count -expandproperty count) `n`n" write-host " STATE ----------------- OBJECT`n`n" foreach ($object in $MonitoringObjects) { switch ($object.HealthState) { "Success" {write-host " " -NoNewline ; write-host -ForegroundColor green $object.HealthState -NoNewline ; write-host " -------- " -NoNewline ; write-host $object.FullName} "Error" {write-host " " -NoNewline ; write-host -ForegroundColor red $object.HealthState -NoNewline ; write-host " -------- " -NoNewline ;write-host $object.FullName} "Warning" {write-host " " -NoNewline ; write-host -ForegroundColor yellow $object.HealthState -NoNewline ; write-host " -------- " -NoNewline ;write-host $object.FullName} "Uninitialized" {write-host " " -NoNewline ; write-host -ForegroundColor blue $object.HealthState -NoNewline ; write-host " -------- " -NoNewline ;write-host $object.FullName} } } "`n" } #Fermeture de la connexion Get-SCOMManagementGroupConnection | Remove-SCOMManagementGroupConnection

SCOM – Script Rapport Etat des instances d’une liste de classe (Sortie Html)

Ci-dessous la version Rapport Html du script de l’état des instances d’une liste de classe.

#SCOM - SCRIPT DE REQUETE D'ETAT DES OBJETS D'UNE LISTE DE CLASSE (AVEC GENERATION RAPPORT HTML) #Variables $MGroup = "MyGroup" $MS= "MyMS" $cred = Get-Credential "MyDomain" #Liste de classe a recuperer $ClassList = ('SQL DB Engine','SQL Database','SQL DB File','SQL Agent','SQL Reporting Services','SQL Analysis Services') $backcolor = "#E0ECF8" #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 #Recuperation des classes $MonitoringClasses = $ClassList | foreach {Get-SCOMClass -DisplayName $_} if ($MonitoringClasses -eq $null) { write-host "ERROR - UNABLE TO RETRIEVE CLASSES" -ForegroundColor red } $report = "<style>BODY{background-color:$backcolor;}</style>" $report = $report + "<br/>" $report = $report + "############################################################################## <br/>" $report = $report + "SCOM Management Group: <b>$MGroup</b> <br/>" $report = $report + "############################################################################## <br/><br/>" #Recuperation des instances de la classe foreach ($class in $MonitoringClasses) { $MonitoringObjects = $class | Get-SCOMClassInstance -erroraction silentlycontinue | Sort-Object -Descending -Property HealthState $classdisplayname = $class.displayname $report = $report + "&emsp;&emsp;**************************************************************** <br/>" $report = $report + "&emsp;&emsp;*** OBJECTS OF CLASS <b>$classdisplayname</b> <br/>" $report = $report + "&emsp;&emsp;**************************************************************** <br/>" $report = $report + "&emsp;&emsp;--- $(get-date -Format F) --- <br/><br/>" $report = $report + "&emsp;&emsp;NUMBER OF OBJECT: $($MonitoringObjects | measure-object | select-object -property count -expandproperty count) <br/><br/>" $report = $report + "&emsp;&emsp;STATE ---------- OBJECT <br/><br/>" foreach ($object in $MonitoringObjects) { switch ($object.HealthState) { "Success" {$report = $report + $("&emsp;&emsp;"; "<font color=#00DF00>" ; $object.HealthState ; "</font>" ; "--------" ; $object.FullName ; "<br/>")} "Error" {$report = $report + $("&emsp;&emsp;";"<font color=#FF0000>" ; $object.HealthState ; "</font>" ; "--------" ; $object.FullName ; "<br/>")} "Warning" {$report = $report + $("&emsp;&emsp;";"<font color=#FFFF00>" ; $object.HealthState ; "</font>" ; "--------" ; $object.FullName ; "<br/>")} "Uninitialized" {$report = $report + $("&emsp;&emsp;";"<font color=#0000FF>" ; $object.HealthState ; "</font>" ; "--------" ; $object.FullName ; "<br/>")} } } $report = $report + "<br/><br/><br/>" } ConvertTo-Html -Body $report | Set-Content P:\InstanceList.htm #Fermeture de la connexion Get-SCOMManagementGroupConnection | Remove-SCOMManagementGroupConnection #Execution du html Invoke-Expression P:\InstanceList.htm

SCOM – Script Rapport Etat des instances d’une liste de classe (Sortie Cmdline)

Le script ci-dessous génère un rapport formaté dans la ligne de commande, de l’état des instances d’une liste de classe.

 

#SCOM - SCRIPT DE REQUETE D'ETAT DES OBJETS D'UNE LISTE DE CLASSE #Variables $MGroup = "MyGroup" $MS= "MyMS" $cred = Get-Credential "MyDomain\" #Liste de classe a recuperer $ClassList = ('SQL DB Engine','SQL Database','SQL DB File','SQL Agent','SQL Reporting Services','SQL Analysis Services') #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 #Recuperation des classes $MonitoringClasses = $ClassList | foreach {Get-SCOMClass -DisplayName $_} if ($MonitoringClasses -eq $null) { write-host "ERROR - UNABLE TO RETRIEVE CLASSES" -ForegroundColor red } write-host "#################################################### `n" write-host "SCOM Management Group: $MGroup `n" write-host "#################################################### `n`n" #Recuperation des instances de chaque classe foreach ($class in $MonitoringClasses) { $MonitoringObjects = $class | Get-SCOMClassInstance -erroraction silentlycontinue | Sort-Object -Descending -Property HealthState write-host -BackgroundColor white -ForegroundColor blue " **************************************************************** `n" write-host -BackgroundColor white -ForegroundColor blue " *** OBJETS DE LA CLASSE "$class.displayname" `n" write-host -BackgroundColor white -ForegroundColor blue " **************************************************************** `n`n" write-host " --- $(get-date -Format F) --- `n`n" write-host " NUMBER OF OBJECT: $($MonitoringObjects | measure-object | select-object -property count -expandproperty count) `n`n" write-host " STATE ----------------- OBJECT`n`n" foreach ($object in $MonitoringObjects) { switch ($object.HealthState) { "Success" {write-host " " -NoNewline ; write-host -ForegroundColor green $object.HealthState -NoNewline ; write-host " -------- " -NoNewline ; write-host $object.FullName} "Error" {write-host " " -NoNewline ; write-host -ForegroundColor red $object.HealthState -NoNewline ; write-host " -------- " -NoNewline ;write-host $object.FullName} "Warning" {write-host " " -NoNewline ; write-host -ForegroundColor yellow $object.HealthState -NoNewline ; write-host " -------- " -NoNewline ;write-host $object.FullName} "Uninitialized" {write-host " " -NoNewline ; write-host -ForegroundColor blue $object.HealthState -NoNewline ; write-host " -------- " -NoNewline ;write-host $object.FullName} } } "`n" } #Fermeture de la connexion Get-SCOMManagementGroupConnection | Remove-SCOMManagementGroupConnection

Active Directory : Réinitialiser les mots de passe en masse avec Powershell

Bonjour,

Suite à une demande client voici un script qui permet de réinitialiser les mots de passe d'utilisateurs via un fichier CSV.

Présentation du fichier CSV :

 Dans le fichier csv, nous avons renseigné la liste des comptes utilisateurs dont le mot de passe doit être réinitialisé; afin de limiter les erreurs, nous nous appuyons sur le "SamAccountName".

Présentation du Script :

 

# Réinitialisation des mots de passe utilisateurs à  partir d'un fichier Csv

# Définition des variables de bases

$Server ="DC01.lab.info"  # Déclarez ici le serveur d'exécution
$Input ="C:\Mon_Dossier\Mon_Fichier.csv" # Entrez Ici le chemin d'accès à son fichier csv
$LogFolder = "C:\LogMathieu" # Déclarez ici l'emplacement du répertoire de Log
$Folder = "LogMathieu" # Déclarez ici le nom du répertoire de Log
$LogFile = "C:\LogMathieu\LogScript.txt" # Déclarez ici l'emplacement du fichiers de Log du script
$File = "LogScript.txt" # Déclarez ici le nom du fichier de Log du script
$LogError = "C:\LogMathieu\LogError.txt" # Déclarez ici l'emplacement du fichier d'erreur global
$LogCatch = "C:\LogMathieu\LogCatch.txt" # Déclarez ici l'emplacement du fichier de gestion de l'erreur
$FileCatch = "LogCatch.txt" # Déclarez ici le nom du fichier de gestion de l'erreur 

# Avant de commencer nous allons créer un répertoire et un fichier pour les logs 
 
if (!(Test-Path $logfolder)) {
 
    New-Item -Name $Folder -Path C:\ -type directory
    New-Item -Name $File -Path $LogFolder -type file
    New-Item -Name $FileCatch -Path $LogFolder -type file
    Write-Output "Le dossier $Folder n'existait pas, création du Dossier $Folder, du fichier $File et $FileCatch" | Add-Content $LogFile
                                }
Else {
    Write-Output "Le dossier $Folder existe déjà!" | Add-Content $LogFile
        }
 
# Import du module Active Directory et import du fichier csv
 
Import-Module ActiveDirectory

Import-Csv -Path $Input | Foreach-Object{
    $SAN=$_."User"

    Try {
        Set-ADAccountPassword -Identity "$SAN" -NewPassword:(ConvertTo-SecureString -AsPlainText "P@ssw0rd" -Force) -Reset:$True -Server:$Server | Set-ADUser -ChangePasswordAtLogon:$true -ErrorAction Stop -ErrorVariable PB
            }
    Catch {
        "Une erreur $PB a eu lieu à  $((Get-Date).DateTime)" | Add-Content $LogCatch
            }
    Finally{
        "Fin de l'opération"
            }
                                            }

$Error > $LogError

 

Active Directory : Importation d'utilisateurs en masse avec Powershell

Bonjour,

Je vous présente un petit script powershell que j'utilise pour réaliser des maquettes ou en production selon le besoin.

Le but de ce script est de pouvoir créer et renseigner des comptes utilisateurs a partir d'un fichier CSV contenant les informations relatives aux comptes.

Ce dernier permet dans un active directory :

  • De tester la présence des Unités d'Organisations et les créer si elles n'existent pas.
  • De tester si les utilisateurs existent (le test est basé sur le SamAccountName).
  • De créer les comptes utilisateurs avec les informations renseignées.
  • De définir un de mot passe.
  • D'activer les comptes.
  • De placer les utilisateurs dans les bonnes Unités d'Organisations.

Présentation du CSV

Dans ce cas de figure je remplis un certain nombre de champs, mais en fonction de ce que l'on souhaite renseigner dans le compte utilisateur il suffit d'incrémenter le fichier CSV et bien sur d'ajouter les paramètres associés dans la ligne de code permettant la création de l'utilisateur.  

Le fichier csv a été réalisé avec l'application excel et contient les informations suivantes :

  • GivenName : Le Prénom
  • Surname : Le Nom
  • Name : Prénom Nom
  • SammAccountName : L'identifiant
  • DisplayName : Le nom d'affichage
  • Description : Une description du compte
  • Company : Le nom de la société
  • Department : Le nom du Service
  • EmailAddress : L'adresse mail
  • OfficePhone : Le numéro de téléphone
  • Title : L'intitulé du poste
  • OrganizationalUnit : L'unité d'organisation dans laquelle sera placé le compte

 

Une fois le fichier créé, enregistrez le au format "CSV", notez le chemin d'accès au fichier dans un coin il vous servira ultérieurement.

Présentation du Script

  

 Ci dessous le script Powershell, j'attire votre attention sur le fait qu'il fonctionne pour des Unités d'Organisation de premier niveau si vous possédez ou souhaitez utiliser des sous OU il faudra faire des modifications dans le script (voir la partie Bonus plus bas).

# Script de création d'Utilisateur

#Déclaration des variables
$Domain = "Lab"  # Déclarez ici votre Domaine
$Ext = "info"  # Déclarez ici l'extension (com, info, lan, local....)
$Server ="DC01.lab.info"  # Déclarez ici le serveur d'exécution
$FQDN ="@lab.info"  # Déclarez ici le nom du Domaine précédé de "@" cela servira pour la création du UserPrincipalName
$LogFolder = "C:\LogMathieu" # Déclarez ici l'emplacement du répertoire de Log
$Folder = "LogMathieu" # Déclarez ici le nom du répertoire de Log
$LogFile = "C:\LogMathieu\LogScript.txt" # Déclarez ici l'emplacement du fichiers de Log du script
$File = "LogScript.txt" # Déclarez ici le nom du fichier de Log du script
$LogError = "C:\LogMathieu\LogError.txt" # Déclarez ici l'emplacement du fichier d'erreur global 
$LogCatch = "C:\LogMathieu\LogCatch.txt" # Déclarez ici l'emplacement du fichier de gestion de l'erreur
$FileCatch = "LogCatch.txt" # Déclarez ici le nom du fichier de gestion de l'erreur
$CSV = "C:\Users\Mathieu\Desktop\Import\Utilisateurs_Maquette.csv" # Déclarez ici le chemin d'accès à votre fichier csv


# Avant de commencer nous allons créer un répertoire et un fichier pour les logs


if (!(Test-Path $logfolder)) {

    New-Item -Name $Folder -Path C:\ -type directory
    New-Item -Name $File -Path $LogFolder -type file
    New-Item -Name $FileCatch -Path $LogFolder -type file
    Write-Output "Le dossier $Folder n'existait pas, création du Dossier $Folder, du fichier $File et $FileCatch" | Add-Content $LogFile
                                }
Else {
    Write-Output "Le dossier $Folder existe déjà!" | Add-Content $LogFile
        }

# Import du module Active Directory et import du fichier csv

Import-Module ActiveDirectory

Import-Csv -Delimiter ";" -Path $CSV | ForEach-Object {
    $OU =$_."OrganizationalUnit"

    # Test de la présence de l'unité d'organisation et création si elle n'existe pas

    if ((Get-ADOrganizationalUnit -Filter {Name -eq $OU}) -eq $null) {
        Write-Output "l'unité d'organisation $OU n'existe pas, création de la nouvelle Unité d'organisation" | Add-Content $LogFile
        Try {
            New-ADOrganizationalUnit -Name $OU -Path "DC=$Domain,DC=$Ext" -ErrorAction Stop -ErrorVariable eOU
                }
        Catch{
            "Une erreur $eOU a eu lieu à $((Get-Date).DateTime)"  | Add-Content $LogCatch
                }
        Finally{
            "Fin de l'opération Ajout d'une OU"
                }
                                                                        }
    Else {
        Write-Output "l'unité d'organisation $OU existe déjà" | Add-Content $LogFile
            }
    $User =$_."SamAccountName"
    $DisplayName =$_."DisplayName"
    $GivenName =$_."GivenName"
    $Name =$_."Name"
    $SamAccountName =$_."SamAccountName"
    $Surname =$_."Surname"
    $Description =$_."Description"
    $Company = $_."Company"
    $Department = $_."Department"
    $EmailAddress =$_."EmailAdress"
    $OfficePhone  =$_."OfficePhone"
    $Title =$_."Title"

    # Test de la présence de l'utilisateur et création si il n'existe pas

    if ((Get-ADUser -Filter {SamAccountName -eq $User}) -eq $null) {
        Write-Output "l'utilisateur $User n'existe pas, création du nouvel utilisateur" | Add-Content $LogFile
        Try {
            New-ADUser -Company:$Company -Department:$Department -DisplayName:$DisplayName -GivenName:$GivenName -Name:$Name -Description:$Description -EmailAddress:$EmailAddress -OfficePhone:$OfficePhone -Title:$Title -Path:"OU=$OU,DC=$Domain,DC=$Ext" -SamAccountName:$SamAccountName -Server:"$Server" -Surname:$Surname -Type:"user" -UserPrincipalName:"$SamAccountName$FQDN"  -AccountPassword:(ConvertTo-SecureString -AsPlainText "p@ssw0rd" -Force) -Enabled:$true -AccountNotDelegated:$false -AllowReversiblePasswordEncryption:$false -CannotChangePassword:$false -PasswordNeverExpires:$false -ChangePasswordAtLogon:$true -ErrorAction Stop -ErrorVariable eUser
                }
    Catch{
        "L'erreur $eUser s'est produite à $((Get-Date).DateTime)" | Add-Content $LogCatch
            }
    Finally{
        "Fin de l'opération Ajout d'un Utilisateur"
            }
                                                                        }
    Else {
        Write-Output "l'utilisateur existe déjà" | Add-Content $LogFile
            }
                                                                                                                    }

# Récupérations des erreurs

$Error > $LogError

 

Bonus :

 Si vous souhaitez utiliser des "sous OU" il vous faudra modifier des éléments dans le fichier csv et le script.

Dans le fichier csv: 

Créez de nouvelles colonnes "OrganizationalUnit" et incrémentez les avec un numéro soit par exemple : OrganizationalUnit1,OrganizationalUnit2,OrganizationalUnit3.

Ensuite placez y les noms des untiés d'organistation de la plus basse à la plus haute, par exemple : 

  1.  LAB.INFO\IT\Réseau\Prestataires\PI Services
  2. LAB.INFO\IT\Systèmes\Windows\Stagiaire

Dans le fichier Script:

Il ne vous restera plus qu'à faire les modifications suivantes :

  1. Déclarez les nouvelles variables "OrganizationalUnit1,OrganizationalUnit2,OrganizationalUnit3" (Ligne 38 dans le script avant modification).
  2. Modifier le "path" en ajoutant "OU=$OU1,OU=$OU2,OU=$OU3" devant "DC=$Domain,DC=$Ext" (ligne 44 dans le script avant modification).
  3. Modifier le "path" en ajoutant "OU=$OU,OU=$OU1,OU=$OU2,OU=$OU3" devant "DC=$Domain,DC=$Ext" (ligne 74 dans le script avant modification) attention ici ce n'est pas tout à fait pareil que l'étape 3.

Ceci n'est qu'un exemple bien sur, il vous est tout à fait possible de créer directement une variable $Path et renseigner le chemin complet dans votre csv.