[PSH] Les alarmes de datastore qui manquent à vCenter (par cluster)

Suite à notre post sur la création d’alarmes de latence pour les datastore, nous nous sommes aperçu que sur des environnements relativement important cela pouvait générer une quantité importante d’events inutiles. En effet, les alarmes étant créées à la “racine” du vCenter et propagées sur tous les hosts par héritage, il est fréquent de voir des events liés à une alarme (green>gray et gray>green lors d’un reboot par exemple) d’un datastore n’existant pas sur l’ESX en question. Nous avons donc modifiés nos onliner pour que les alarmes soient créées à la “racine” des cluster et comme le nom d’une alarme doit être unique, nous y avons rajouté le nom du cluster :

Alarme de latence Read ou Write pour datastore partagé NFS par cluster, yellow 300ms/5min et red 500ms/3min (mailto:admin@vmware.local) :

foreach ($vicluster in Get-View -ViewType ClusterComputeResource) {foreach ($dsname in ($vicluster.Datastore|%{Get-View $_}|?{$_.summary.Accessible -and $_.summary.MultipleHostAccess -and $_.info.nas})){if (!((Get-View AlarmManager).GetAlarm($vicluster.moref)|?{(get-view $_).info.name -match "Datastore $($dsname.name) datastore RW latency"})){(Get-View AlarmManager).CreateAlarm($vicluster.moref,(New-Object VMware.Vim.AlarmSpec -Property @{Name = "Datastore $($dsname.name) datastore RW latency in $($vicluster.name)";Description = "Custom alarm to monitor NFS $($dsname.name) ($($dsname|%{$_.Host}|%{$_.MountInfo.Path.split("/")[-1]}|sort -unique)) read or write latency in $($vicluster.name)";Enabled = $true;expression = (New-Object VMware.Vim.OrAlarmExpression -Property @{expression = @((New-Object VMware.Vim.MetricAlarmExpression -Property @{Metric = (New-Object VMware.Vim.PerfMetricId -Property @{CounterId = ((Get-View (Get-View ServiceINstance).Content.PerfManager).PerfCounter|?{$_.groupinfo.key -match "datastore"}|?{$_.nameinfo.key -match "totalReadLatency"}|?{$_.RollupType -match "average"}).key;Instance = ($dsname|%{$_.Host}|%{$_.MountInfo.Path.split("/")[-1]}|sort -unique)});Operator = "isAbove";Yellow = "300";YellowInterval = "300";Red = "500";RedInterval = "180";Type = "HostSystem"});(New-Object VMware.Vim.MetricAlarmExpression -Property @{Metric = (New-Object VMware.Vim.PerfMetricId -Property @{CounterId = ((Get-View (Get-View ServiceINstance).Content.PerfManager).PerfCounter|?{$_.groupinfo.key -match "datastore"}|?{$_.nameinfo.key -match "totalWriteLatency"}|?{$_.RollupType -match "average"}).key;Instance = ($dsname|%{$_.Host}|%{$_.MountInfo.Path.split("/")[-1]}|sort -unique)});Operator = "isAbove";Yellow = "300";YellowInterval = "300";Red = "500";RedInterval = "180";Type = "HostSystem"}))});Action=(New-Object VMware.Vim.GroupAlarmAction -Property @{Action= (New-Object VMware.Vim.AlarmTriggeringAction -Property @{Action = (New-Object VMware.Vim.SendEmailAction -Property @{ToList = "admin@vmware.local";Subject = "[vAlarm] $($dsname.name) RW latency on {targetName}";CcList = "";Body = ""});TransitionSpecs = @((New-Object VMware.Vim.AlarmTriggeringActionTransitionSpec -Property @{StartState = "green";FinalState = "yellow";Repeats = $false});(New-Object VMware.Vim.AlarmTriggeringActionTransitionSpec -Property @{StartState = "yellow";FinalState = "red";Repeats = $false}))})});ActionFrequency = "1800"}))}}}

Alarme de latence Read ou Write pour datastore partagé VMFS par cluster, yellow 30ms/5min et red 40ms/3min (mailto:admin@vmware.local) :

foreach ($vicluster in Get-View -ViewType ClusterComputeResource) {foreach ($dsname in ($vicluster.Datastore|%{Get-View $_}|?{$_.summary.Accessible -and $_.summary.MultipleHostAccess -and $_.info.vmfs})){if (!((Get-View AlarmManager).GetAlarm($vicluster.moref)|?{(get-view $_).info.name -match "Datastore $($dsname.name) RW latency in $($vicluster.name)"})){(Get-View AlarmManager).CreateAlarm($vicluster.moref,(New-Object VMware.Vim.AlarmSpec -Property @{Name = "Datastore $($dsname.name) RW latency in $($vicluster.name)";Description = "Custom alarm to monitor VMFS $($dsname.name) ($($dsname|%{$_.Host}|%{$_.MountInfo.Path.split("/")[-1]}|sort -unique)) read or write latency in $($vicluster.name)";Enabled = $true;expression = (New-Object VMware.Vim.OrAlarmExpression -Property @{expression = @((New-Object VMware.Vim.MetricAlarmExpression -Property @{Metric = (New-Object VMware.Vim.PerfMetricId -Property @{CounterId = ((Get-View (Get-View ServiceINstance).Content.PerfManager).PerfCounter|?{$_.groupinfo.key -match "datastore"}|?{$_.nameinfo.key -match "totalReadLatency"}|?{$_.RollupType -match "average"}).key;Instance = ($dsname|%{$_.Host}|%{$_.MountInfo.Path.split("/")[-1]}|sort -unique)});Operator = "isAbove";Yellow = "30";YellowInterval = "300";Red = "40";RedInterval = "180";Type = "HostSystem"});(New-Object VMware.Vim.MetricAlarmExpression -Property @{Metric = (New-Object VMware.Vim.PerfMetricId -Property @{CounterId = ((Get-View (Get-View ServiceINstance).Content.PerfManager).PerfCounter|?{$_.groupinfo.key -match "datastore"}|?{$_.nameinfo.key -match "totalWriteLatency"}|?{$_.RollupType -match "average"}).key;Instance = ($dsname|%{$_.Host}|%{$_.MountInfo.Path.split("/")[-1]}|sort -unique)});Operator = "isAbove";Yellow = "30";YellowInterval = "300";Red = "40";RedInterval = "180";Type = "HostSystem"}))});Action=(New-Object VMware.Vim.GroupAlarmAction -Property @{Action= (New-Object VMware.Vim.AlarmTriggeringAction -Property @{Action = (New-Object VMware.Vim.SendEmailAction -Property @{ToList = "admin@vmware.local";Subject = "[vAlarm] $($dsname.name) RW latency on {targetName}";CcList = "";Body = ""});TransitionSpecs = @((New-Object VMware.Vim.AlarmTriggeringActionTransitionSpec -Property @{StartState = "green";FinalState = "yellow";Repeats = $false});(New-Object VMware.Vim.AlarmTriggeringActionTransitionSpec -Property @{StartState = "yellow";FinalState = "red";Repeats = $false}))})});ActionFrequency = "1800"}))}}}

Alarme de latence SIOC Normalized Latency pour datastore partagé par cluster, yellow 30ms/5min et red 40ms/3min (mailto:admin@vmware.local) :

foreach ($vicluster in Get-View -ViewType ClusterComputeResource) {foreach ($dsname in ($vicluster.Datastore|%{Get-View $_}|?{$_.summary.Accessible -and $_.summary.MultipleHostAccess -and $_.IormConfiguration.Enabled})){if (!((Get-View AlarmManager).GetAlarm($vicluster.moref)|?{(get-view $_).info.name -match "Datastore $($dsname.name) SIOC Normalized Latency in $($vicluster.name)"})){(Get-View AlarmManager).CreateAlarm($vicluster.moref,(New-Object VMware.Vim.AlarmSpec -Property @{Name = "Datastore $($dsname.name) SIOC Normalized Latency in $($vicluster.name)";Description = "Custom alarm to monitor $($dsname.name) ($($dsname|%{$_.Host}|%{$_.MountInfo.Path.split("/")[-1]}|sort -unique)) datastore SIOC Normalized Latency in $($vicluster.name)";Enabled = $true;expression = (New-Object VMware.Vim.OrAlarmExpression -Property @{expression = @((New-Object VMware.Vim.MetricAlarmExpression -Property @{Metric = (New-Object VMware.Vim.PerfMetricId -Property @{CounterId = ((Get-View (Get-View ServiceINstance).Content.PerfManager).PerfCounter|?{$_.groupinfo.key -match "datastore"}|?{$_.nameinfo.key -match "sizeNormalizedDatastoreLatency"}|?{$_.RollupType -match "average"}).key;Instance = ($dsname|%{$_.Host}|%{$_.MountInfo.Path.split("/")[-1]}|sort -unique)});Operator = "isAbove";Yellow = "30000";YellowInterval = "300";Red = "40000";RedInterval = "180";Type = "HostSystem"}))});Action=(New-Object VMware.Vim.GroupAlarmAction -Property @{Action= (New-Object VMware.Vim.AlarmTriggeringAction -Property @{Action = (New-Object VMware.Vim.SendEmailAction -Property @{ToList = "admin@vmware.local";Subject = "[vAlarm] $($dsname.name) SIOC Normalized Latency on {targetName}";CcList = "";Body = ""});TransitionSpecs = @((New-Object VMware.Vim.AlarmTriggeringActionTransitionSpec -Property @{StartState = "green";FinalState = "yellow";Repeats = $false});(New-Object VMware.Vim.AlarmTriggeringActionTransitionSpec -Property @{StartState = "yellow";FinalState = "red";Repeats = $false}))})});ActionFrequency = "1800"}))}}}

Alarme de Disk Command aborts pour datastore VMFS partagé par cluster, en cas de défaillance/saturation DAS/SAN/iSCSI (mailto:admin@vmware.local) :

foreach ($vicluster in Get-View -ViewType ClusterComputeResource) {foreach ($diskname in ($vicluster.Datastore|%{Get-View $_}|?{$_.info.vmfs -and $_.summary.Accessible -and $_.summary.MultipleHostAccess}|%{$_.info.vmfs.extent}|%{$_.diskname})){if (!((Get-View AlarmManager).GetAlarm($vicluster.moref)|?{(get-view $_).info.name -match "Disk $diskname command aborts"})){(Get-View AlarmManager).CreateAlarm($vicluster.moref,(New-Object VMware.Vim.AlarmSpec -Property @{Name = "Disk $diskname command aborts in $($vicluster.name)";Description = "Custom alarm to monitor $diskname disk command aborts in $($vicluster.name)";Enabled = $true;expression = (New-Object VMware.Vim.OrAlarmExpression -Property @{expression = (New-Object VMware.Vim.MetricAlarmExpression -Property @{Metric = (New-Object VMware.Vim.PerfMetricId -Property @{CounterId = ((Get-View (Get-View ServiceINstance).Content.PerfManager).PerfCounter|?{$_.groupinfo.key -match "disk"}|?{$_.nameinfo.key -match "commandsAborted"}|?{$_.GroupInfo.Key -ne "virtualDisk"}|?{$_.RollupType -match "summation"}).key;Instance = $diskname});Operator = "isAbove";Yellow = "1";Red = "2";Type = "HostSystem"})});Action=(New-Object VMware.Vim.GroupAlarmAction -Property @{Action= (New-Object VMware.Vim.AlarmTriggeringAction -Property @{Action = (New-Object VMware.Vim.SendEmailAction -Property @{ToList = "admin@vmware.local";Subject = "[vAlarm] command aborts on disk $diskname on {targetName}";CcList = "";Body = ""});TransitionSpecs = @((New-Object VMware.Vim.AlarmTriggeringActionTransitionSpec -Property @{StartState = "green";FinalState = "yellow";Repeats = $false});(New-Object VMware.Vim.AlarmTriggeringActionTransitionSpec -Property @{StartState = "yellow";FinalState = "red";Repeats = $true}))})});ActionFrequency = "1800"}))}}}

Tags: , , , , , , ,

Templates ZFS pour cacti

Nous avons enfin terminé le fignolage des tous les graphs cacti dont nous nous servons pour la supervision de nos appliances Nexenta, il était donc temps d’en faire profiter la communauté !

Tout comme pour notre post sur le monitoring smart, le tout se fait uniquement dans le fichier snmpd.conf sans script annexe. Pour rappel, l’édition de la config snmp sous nexenta se fait via la nmc avec la commande suivante :

setup network service snmp-agent edit-settings snmpd.conf

Pour chaque graphique, il faudra ajouter une ou plusieurs lignes à la config snmp et importer le template dans cacti.

extend .1.3.6.1.4.1.2021.85 arc_meta_max /bin/bash -c "echo ::arc | mdb -k| grep arc_meta_max|tr -cd '[:digit:]'"
extend .1.3.6.1.4.1.2021.85 arc_meta_used /bin/bash -c "echo ::arc | mdb -k| grep arc_meta_used|tr -cd '[:digit:]'"
extend .1.3.6.1.4.1.2021.85 arc_size /bin/bash -c "echo ::arc | mdb -k| grep -w size|tr -cd '[:digit:]'"
extend .1.3.6.1.4.1.2021.85 arc_meta_limit /bin/bash -c "echo ::arc | mdb -k| grep arc_meta_limit|tr -cd '[:digit:]'"
extend .1.3.6.1.4.1.2021.85 arc_meta_c_max /bin/bash -c "echo ::arc | mdb -k| grep c_max|tr -cd '[:digit:]'"

Graph template à importer dans cacti : ZFS – ARC Usage

extend .1.3.6.1.4.1.2021.89 arc_hits /bin/bash -c "kstat -p ::arcstats:hits| cut -s -f 2"
extend .1.3.6.1.4.1.2021.89 arc_misses /bin/bash -c "kstat -p ::arcstats:misses| cut -s -f 2"

Graph template à importer dans cacti : ZFS – ARC Stats

extend .1.3.6.1.4.1.2021.89 arc_l2_hits /bin/bash -c "kstat -p ::arcstats:l2_hits| cut -s -f 2"
extend .1.3.6.1.4.1.2021.89 arc_l2_misses /bin/bash -c "kstat -p ::arcstats:l2_misses| cut -s -f 2"

Graph template à importer dans cacti : ZFS – L2ARC Stats

extend .1.3.6.1.4.1.2021.90 vopstats_zfs_nread /bin/bash -c "kstat -p ::vopstats_zfs:nread | cut -s -f 2"
extend .1.3.6.1.4.1.2021.90 vopstats_zfs_nwrite /bin/bash -c "kstat -p ::vopstats_zfs:nwrite | cut -s -f 2

Graph template à importer dans cacti : ZFS – VFS IOPS

extend .1.3.6.1.4.1.2021.90 vopstats_zfs_read_bytes /bin/bash -c "kstat -p ::vopstats_zfs:read_bytes | cut -s -f 2"
extend .1.3.6.1.4.1.2021.90 vopstats_zfs_write_bytes /bin/bash -c "kstat -p ::vopstats_zfs:write_bytes | cut -s -f 2"

Graph template à importer dans cacti : ZFS – VFS Throughput

extend .1.3.6.1.4.1.2021.88 zpool_name /bin/bash -c "zpool list -H -o name"
extend .1.3.6.1.4.1.2021.88 zpool_snap /bin/bash -c "zpool list -Ho name|for zpool in `xargs`;do zfs get -rHp -o value usedbysnapshots $zpool|awk -F: '{sum+=$1} END{print sum}';done"
extend .1.3.6.1.4.1.2021.88 zpool_used /bin/bash -c "zpool list -Ho name|xargs zfs get -Hp -o value used"
extend .1.3.6.1.4.1.2021.88 zpool_data_used /bin/bash -c "zpool list -Ho name|for zpool in `xargs`;do snap=`zfs get -rHp -o value usedbysnapshots $zpool|awk -F: '{sum+=$1} END{print sum}'`;pool=`zfs get -Hp -o value used $zpool`; echo $pool $snap|awk '{print (\$1-\$2);}';done"
extend .1.3.6.1.4.1.2021.88 zpool_available /bin/bash -c "zpool list -Ho name|xargs zfs get -Hp -o value available"
extend .1.3.6.1.4.1.2021.88 zpool_capacity /bin/bash -c "zpool list -H -o capacity|cut -d % -f 1"

Script à copier dans le répertoire ”/resource/snmp_queries/” : ZFS – zpool usage
Graph template à importer dans cacti : ZFS – zpool usage
Ce dernier graph est similaire à celui que nous avions posté il y a quelques temps mais permet de distinguer la consommation des data de celle des snapshot.

extend .1.3.6.1.4.1.2021.84 busy /bin/bash -c "iostat -xrn 1 3|grep -E 'c2t'|grep -vE c2t15d0|tail -\$((\$(paste -d= <(iostat -x | tail -n +3 | awk '{print \$1}') <(iostat -nx | tail -n +3 | awk '{print \"/dev/dsk/\"\$11}')|grep -E 'c2t'|grep -vE c2t15d0|wc -l)*2))| awk -F',' 'BEGIN { n=0; sum=0; } { n++; sum += \$(NF-1); } END { printf (\"%.2f\",sum / n); }'|awk '{ printf (\"%d\", (\$1 > 100) ? 0 : \$1); }'"

Graph template à importer dans cacti : ZFS – disk busy
Ce graph est expérimentale et spécifique dans la mesure où il représente la charge estimée des disk filtrés par les differents grep de la commande, à ajuster en fonction de la cible. Le scénario cible idéal est un système avec un seul zpool (mis à part celui du système). Dans notre exemple, nous avons limité à tous les disques dont les noms commencent par “c2t” et exclu “c2t15d0″ (hot spare dans ce cas).

Tags:

vpxd 2 syslog

Voila un certain temps que nous cherchions une méthode “pas-trop-crade” pour rediriger les logs du service vCenter (sous windows) vers un serveur syslog qui centraliserai esxi et vpxd. Nous éviterons de vous raconter dans le détail l’idée de départ en autoIT+powershell+taches planifiées pour directement passer à la solution  *qui-brille-dans-la-nuit* :)

Plutôt que de monter une usine à gaz comme notre ami William (qui ne semble pas porter windows dans son coeur – just kidding William ;) ), nous avons fait le tour des agents capables de forwarder des fichiers log vers du syslog, gratos évidement. Le plus satisfaisant semble être Epilog for Windows qui reconnait par défaut plusieurs formats de log (IIS, Exchange, Apache, etc…) et qui dispose même de sa propre interface web (comme tous les agents snare) :

Nous avons toute fois du faire face à un petit problème concernant le patern de fichier à fournir à Epilog car “vpxd-*.log” correspond à plusieurs types de log dans le répertoire logs du vcenter (vpxd-, vpxd-alert- et vpxd-profiler-) et, contrairement à linux, il n’existe pas de fichier vpxd.log pour simplifier la chose. Heureusement, VMware semble avoir quand même prévu le coup car il est possible de changer le prefix du log en rajoutant une ligne dans le vpxd.cfg (nous avons choisi “vpxdsvc”) :

<name>vpxdsvc</name>

Il suffit ensuite de configurer le serveur de destination et de sélectionner le format syslog :

On obtient alors quelque chose de pas trop mal dans notre appliance Graylog2 (Partylog2) de test (pour celui de prod nous nous sommes inspiré de ce howto sans oublier le trick pour le “too many open files”) :

Tags: , , ,

[SDK] Les petits secrets du HostPatchManager

Pour un projet particulier, il nous a fallu trouver une méthode industrialisable pour patcher des ESXi 4.0 U1 > U4 à chaud et sans maintenance mode. Evidemment la mise à jour nécessite un reboot pour être effective mais cela offre la possibilité (contrairement à VUM) de séparer totalement la partie patch de la partie “maintenance mode”/reboot afin de partager les taches entre 2 équipes par exemple (et accessoirement d’être plus rapide que VUM).

Nous savions que c’était techniquement envisageable compte tenu du fait qu’un patch pour ESXi se résume à la copie d’une nouvelle build dans la “bootbank” après avoir copier la build courante dans la “altbootbank“ la “bootbank” inactive. Compte tenu du fait qu’ESXi est un OS stateless, le fait d’écraser la “bootbank” et la “altbootbank” pendant le fonctionnement ne pose pas de problème. Malgré tout, il nous a fallu chercher un peu pour trouver le bon paramètre à passer à “esxupdate” pour forcer la mise à jour (qui nécessite le “maintenance mode” par défaut) avec des vm en fonctionnement.

Voici un petit oneliner qui vous permettra de reproduire cet exploit (oubliez le support vmware naturellement) :

(get-view (get-vmhost vsp41esx01*|get-view).configmanager.PatchManager).InstallHostPatchV2($null, "http://www.hypervisor.fr/img/ESXi410-201206001.zip", $null, ((new-object Vmware.Vim.HostPatchManagerPatchManagerOperationSpec -Property @{cmdOption = "--maintenancemode"})))

Comme le détail le SDK, il est possible de choisir entre 3 sources de patch : metaUrls, bundleUrls ou vibUrls, tout dépendra du format du patch. Concernant le “maintenance mode”, toute la magie réside dans le paramètre ”–maintenancemode” qui fait parti des “hidden options” d’esxupdate (malheureusement pas toutes commentées) :

–HA
–vib-view
–maintenancemode
–force
–test ‘Test update transaction only–do not change sytem.’
–all ‘Display all bulletins. Default is to display only the applicable updates.’
–long ‘Produce more detailed response in query or info output.’
–noobsoletes ‘Ignore obsoletions during update. (Enables downgrading to older bundles.)’
–reinstall ‘Re-install a bundle that is already installed.’
–nodeps
–nosigcheck
–nocache
–olderversion
–cachesize
–cleancache
–compliant

A l’opposé, il est aussi possible de désinstaller un patch (à chaud toujours), ce qui est malheureusement impossible à faire avec VUM :

(get-view (get-vmhost vsp41esx02*|get-view).configmanager.PatchManager).UninstallHostPatch("ESXi410-201101223-UG",((new-object Vmware.Vim.HostPatchManagerPatchManagerOperationSpec -Property @{cmdOption = "--maintenancemode"})))

Tags: , , , ,

goodbye vmtools modules

Après avoir essayé 36 méthodes qui fonctionnent plus ou moins bien, nous avons la bonne recette (validée en 4.1 et 5.0) pour virer les modules des vmtools qui ne servent à rien (aka les trucs pour Workstation qui servent pas sur ESXi).

En GUI comme en PowerCLI ce sont les mêmes paramètres à passer :

/s /v"/qn ADDLOCAL=ALL REMOVE=Audio,ThinPrint,WYSE,Hgfs REBOOT=ReallySuppress"

Get-VM VM1,VM2,VM3|Get-View|%{$_.UpgradeTools('/s /v"/qn ADDLOCAL=ALL REMOVE=Audio,ThinPrint,WYSE,Hgfs REBOOT=ReallySuppress"')}

La liste des modules est disponible dans la kb 2000399 (le REBOOT=ReallySuppress empêche la vm de rebooter après la mise à jour) et pour l’occasion nous avons créé une belle url mnémotechnique qui vous mènera directement au repository des vmtools chez VMware : vmtools.vmwa.re

Tags: ,