NetBackup+InfiniteLoop+Snapshot=Bad

Update 29/01/2014: Raphaël a publié sur son dépot de OneLiner une commande pour retourner la liste des VM sans snapshots ayant des vmdk delta (snapshot “cachés”)

On a rencontré un problème assez intéressant récemment avec un serveur ESXi 5.0 qui a perdu la connexion avec le vCenter :

Bien que le serveur ESXi était passé en état disconnected, les machines virtuelles hébergées dessus continuaient de tourner sans problèmes, heureusement que le soucis n’était pas sur la ParentVM d’un Hyper-V, l’état des VM aurait été différent :p

Bref, les rapports vCheck nous ont remontés des erreurs assez bizarres par rapport au serveur qui avait un soucis :

Cannot synchronize host XXX. A general system error occurred: Unexpected exception reading HTTP response body: class Vmacore::Http::TruncatedResponseException(While determining chunk size, truncated HTTP response.) with trace: backtrace[00] rip 000000018013deba (no symbol) backtrace[01] rip 0000000180101518 (no symbol) backtrace[02] rip 0000000180101a5e (no symbol) backtrace[03] rip 000000018008930b (no symbol) backtrace[04] rip 000000018003fd5f (no symbol) backtrace[05] rip 00000001800444ce (no symbol) backtrace[06] rip 00000000005b27e9 (no symbol) backtrace[07] rip 0000000000583b87 (no symbol) backtrace[08]
...

Et une tentative de reconnecter le serveur ESX au vCenter échouait avec les mêmes erreurs :

On voyait énormément d’erreurs dans les logs du style :

column 3836417 while parsing property "parent" of static type VirtualDiskFlatVer2BackingInfo while parsing serialized DataObject of type vim.vm.device.VirtualDisk.FlatVer2BackingInfo at line 7

Vu que l’erreur parlait de VirtualDiskFlatVer2BackingInfo, on s’est dit que cela pouvait être lié à un problème sur les disques VMDK d’une ou plusieurs VM, on a donc commencé a regarder de plus près le dossier de certaines VM et on est tombé sur une VM qui contenait pas moins de 230 snapshots (mais aucun visible depuis la console vSphere) …

Au final, il semblerait que le problème soit venu encore une fois de l’agent NetBackup qui, suite à un incident SAN, ait créé en continue des snapshots sur la VM en cours de sauvegarde sans jamais faire le ménage (jolie boucle) …

Afin de pouvoir reconnecter le serveur au vCenter, il nous a fallu se connecter en direct sur le serveur ESXi et faire un Consolidate des disques des VM ayant eu le problème. Au bout de 5 longues heures de consolidation (on est encore agréablement surpris qu’il n’y ait pas eu plus d’incidence sur le guest), les VM avaient retrouvées leur disques sans snapshot et la reconnexion du serveur ESXi au vCenter a pu se faire sans soucis.

Moralité, Erik Bussink l’a très bien résumé dans sa réponse sur twitter :

Vivement la migration sur Veeam ;p

Hypervisor.fr a mis à jour son dépot de OneLiner pour en intégrer un qui listera les VM avec des snapshots cachés (#OL26 disponible ici http://www.hypervisor.fr/?page_id=3637) :

Get-View -ViewType VirtualMachine|?{!$_.snapshot}|?{$_|%{$_.layoutex.file}|?{$_.name -match "-delta.vmdk$"}}|select name

VMworld 2013

Voici notre revue du VMworld 2013 Europe qui s’est déroulé à Barcelone (encore!) du 14 au 17 Octobre 2013. On voulait vraiment remercier John Troyer et Corey Romero ainsi que toute la communauté VMware de nous avoir permis de participer à ce VMworld !

C’est le 3ème VMworld auquel on va, avec cette fois une motivation un peu différente des années passées : profiter de ces quelques jours de vacances et comme toujours rencontrer du monde !

Cette année encore, les sessions sont accessibles en ligne et disponibles sur http://www.vmworld.com/community/sessions/2013.

De plus, vous pouvez maintenant faire les labs aussi en ligne depuis http://labs.hol.vmware.com/. C’est vraiment une très bonne initiative de la part de VMware, on vous conseille de tester !

Dans les moments sympa de ce VMworld, on a pu aller visiter le VMware Time Machine, une sorte de timeline avec 15 faits marquants pour commémorer les 15 ans de VMware (une version accessible en ligne est disponible ici) :

Et pour ceux qui se demandait encore ce que voulait dire les intiales ESX ou GSX, voici la réponse en image :

Nous sommes aller à la traditionnelle session vBrownBag Tech Talk de William Lam, cette fois-ci intitulée #NotSupported dans laquelle il a pu aborder des Tips/Tricks pour vSphere 5.5 (la vidéo est disponible ici) avec notamment une annonce très attendue de la part de beaucoup (dont nous bien sûr), à savoir la mise a disposition pour bientôt des VMware Tools pour ESXi via une vib (aka vmtools for nested ESXi) :

Une fois sa session terminée, on a pu discuter en off avec William sur plusieurs points (on n’avait pas énormément eu le temps de papoter avec lui l’année dernière, on s’est bien rattrapé cette année :p) dont la nouvelle architecture Native Device Driver d’ESXi 5.5 (dont il parle dans son billet ESXi 5.5 introduces a new Native Device Driver Architecture Part 1).

Pendant ce temps derrière nous, s’installait Frank Denneman pour une interview vidéo sur PernixData (le temps pour nous de prendre quelques photos) :

Une des sessions intéressantes était la BCO5065 – vSphere Fault Tolerance for Multiprocessor VMs Technical Preview. Outre la première partie très théorique, on a pu voir plusieurs démos avec des VM ayant jusqu’à 16 vCPU, donc pour le moins assez bluffant. Cependant, ce n’est qu’une Technical Preview, cad qu’aucune date de sortie n’est prévue (NDA oblige) et surtout qu’aucune information poussée n’a pu être divulguée (toujours un problème de NDA)… Par contre, l’impact sur les performances est assez inquiétant (on espère que le côté Technical Preview explique cela) comme vous pouvez le voir sur la 3ème photo :

On a pu aussi prendre en photo Justin King (aka « vCenter/SSO » guy) pendant la session VSVC4830 – vCenter Deep Dive (vidéo disponible via VMwareTV ici) :

Et que serait un VMworld sans la session d’Alan et Luc : PowerCLI Best Practices – A Deep Dive pendant laquelle on a pu voir entre autre le module PowerCLI gérant la partie VSAN et un exemple sur les Remote Session en PowerShell (expliqué dans le billet de Luc SiW – Robust Sessions and PowerCLI) :

En se balladant dans le Solution Exchange, on a croisé un ami, Didier Pironet (http://deinoscloud.wordpress.com/) sur le stand de Bull (pour qui il travaille actuellement) et on a pu avoir une présentation du serveur Bullion qui pour rappel peut supporter jusqu’à 320 cores et 4TB de RAM, idéal pour héberger des Monster « Melvin » VM (Didier a d’ailleurs écrit une très bonne série de billets sur l’architecture du Bullion ici : http://deinoscloud.wordpress.com/2012/10/29/bulls-bcs-architecture-deep-dive-part-1/)

On s’est aussi arrêté du côté du stand de Dell qui présentait un rack au format tower censé ne pas faire de bruit (donc étant WAF compliant) PowerEdge VRTX, composé de 4 lames et 25 disques SAS 2.5″. Malheureusement, le boitier n’était pas alimenté, on n’a donc pas pu vérifier le côté sonore du boitier, mais vu la composition des ventilateurs/flux d’air, cela nous semblait peu problable que cela soit vraiment installable dans un salon :p

Finalement ce VMworld 2013 était une bonne cuvée, et ce que l’on se rappellera surtout de cette semaine, ce sont les petits déjeuners pris avec Timo et Raphael sur l’avenue de la Rambla de Catalunya (qui a dit vacances ?) :

A l’année prochaine Barcelone pour le VMworld Europe 2014 !

Réplication des custom fields

La plateforme VMware du client chez lequel on travaille aujourd’hui avec hypervisor.fr a plusieurs particularités dont celle d’avoir énormément de custom fields.

Outre le fait de vouloir une certaine cohérence dans tous ces custom fields, on aime bien avoir une plateforme de production « propre » et donc on préferera par exemple avoir un custom field « N/A » plutôt qu’un champs vide (pour éviter des remontées d’alertes), de même qu’éviter les oublis lors de déploiement d’appliance en OVF (qui forcement ne remplisse pas les champs automatiquement).

On a donc développé un script qui permet de répliquer si besoin les custom fields et annotation d’une VM vers une autre afin de pouvoir gagner du temps et se simplifier la vie, et surtout d’éviter un risque d’erreur lors de saisie manuelle. On peut aussi utiliser ce script pour remplir automatiquement les champs d’une VM avec « N/A » (via l’omission du paramètre vmSourceName).

Le script prend plusieurs arguments :

  • vmSourceName (optionnel) : Nom de la VM source utilisée pour la replication
  • vmDestinationName : Nom de la VM destination utilisée pour la replication
  • force (optionnel) : Permet d’écraser les champs existants sur la VM de destination

Il y a tout d’abord une vérification des valeurs passées pour le nom des VM afin de s’assurer que les machines sources et destination existent bien :

Ensuite, la réplication des custom fields et annotation s’effectuent. Si la VM de destination possède déjà des custom fields renseignés, ils ne seront pas écrasés sauf si le switch -force est utilisé :

Voici quelques exemples d’utilisation du script :

C:\foo>.\Set-Tags.ps1 -vmSourceName VM01 -vmDestinationName VM02

Cela va répliquer les custom fields et annotation de la machine virtuelle VM01 vers VM02 (sans écraser les champs renseignés à la destination).

C:\foo>.\Set-Tags.ps1 -vmSourceName VM01 -vmDestinationName VM02 -force

Cela va répliquer les custom fields et annotation de la machine virtuelle VM01 vers VM02 en écrasant les champs renseignés à la destination.

C:\foo> .\Set-Tags.ps1 -vmDestinationName VM02

Cela va remplir les champs de la VM02 avec « N/A » (sans écraser les champs déjà renseignés)

C:\foo> .\Set-Tags.ps1 -vmDestinationName VM02 -force

Cela va remplir les champs de la VM02 avec « N/A » en écrasant les champs déjà renseignés.

Et comme toujours, un petit Get-Help dessus permettra d’avoir l’aide en ligne du cmdlet :

Le script Set-Tags.ps1 est disponible au téléchargement sur notre page GitHub: https://github.com/v-team/powercli-toolbox

Outil lazyMethodEnabler

Pour faire suite au billet de hypervisor.fr Storage vMotion : the method is disabled, on est aujourd’hui dans une nouvelle mission chez un client qui avait trop énormément de machines virtuelles avec les méthodes désactivées (et augmentant quotidiennement au fil des sauvegardes…) :

Sans blâmer l’outil pérave de sauvegarde existant jaune et noir (quoique c’est assez tentant…), le nombre de machines virtuelles touchées étaient trop important pour qu’aucun des workaround de la KB VMware ne soit acceptable. Pour rappel, les workaround proposés sont :

  • unregister/register de la VM (donc là, on oublie les statistiques, custom fields et historique à cause du changement de MoRef > NoWay)
  • Purge manuel de la base de données du vCenter (opération nécessitant un arrêt du service vCenter donc on oublie en production si le problème est récurrent > NoWay)
  • Relancer un job de backup (c’est viable à petite échelle, mais dans notre cas, le nombre de VM ayant ce problème augmentait d’environ 60 tous les jours… > NoWay)

En attendant la migration vers une vraie solution de sauvegarde (le passage vers Veeam Backup se faisant désiré), il fallait quand même trouver une solution plus propre :p

Partant du principe qu’un backup de la VM a des chances de remettre ce paramètre comme il faut, on s’est demandé ce qui provoquait l’erreur. La KB explique :

When a VM-level backup begins, the backup system informs vCenter to disable Storage vMotion for that VM to ensure that the backups can complete successfully

Le passage intéressant est « the backup system informs vCenter« . Après quelques recherches, il s’avère que cela passe par des appels au Virtual Disk Development Kit (VDDK). Histoire de comprendre plus en détails les mécanismes de sauvegarde et de manipulation des fichiers VMDK par les outils tiers, on a commencé à lire le Virtual Disk Programming Guide afin de trouver l’explication.

Outre le côté extrêmement intéressant du SDK (on vous invite d’ailleurs à jeter un coup d’oeil histoire de voir sa richesse), la partie qui nous intéresse se trouve dans Advanced Transport APIs dans l’article Prepare For Access and End Access.

Voici l’extrait qui répond à la question et à notre problème :

The VixDiskLib_PrepareForAccess() function notifies a vCenter-managed host that a virtual machine’s disks are being opened, probably for backup, so the host should postpone virtual machine operations that might interfere with virtual disk access. Call this function before creating a snapshot on a virtual machine. Internally, this function disables the vSphere API method RelocateVM_Task.


The VixDiskLib_EndAccess() function notifies the host that a virtual machine’s disks have been closed, so operations that rely on the virtual disks to be closed, such as vMotion, can now be allowed. Call this function after closing all the virtual disks, and after deleting the virtual machine snapshot. Normally this function is called after previously calling VixDiskLib_PrepareForAccess, but you can call it to clean up after a crash. Internally, this function re-enables the vSphere API method RelocateVM_Task.

La solution se trouve donc au niveau des appels VixDiskLib_PrepareForAccess() et VixDiskLib_EndAccess() qui s’occupent de notifier au serveur vCenter de gérer la partie Method Disabled (permettant ainsi d’éviter un Storage vMotion pendant un backup par exemple).

Par rapport à notre problème, le fait de relancer un job de backup effectue le traitement PrepareForAccess>Backup>EndAccess et donc est bien censé corriger le soucis via l’appel EndAccess(). Partant de ce principe, on s’est donc dit qu’une solution viable à grande échelle (outre changer d’outil de sauvegarde ^^) serait d’avoir un programme qui ne fait que le traitement PrepareForAccess>EndAccess (et donc qui serait beaucoup plus rapide qu’un backup complet de chaque VM).

VDDK étant fait pour les langages C/C++, il a fallu que l’on ressorte de vieux souvenirs sur le développement en C++ (on est effectivement très loin du C# ou PowerShell…). On a donc développer un programme qui va permettre de « réactiver » les méthodes disabled mal enlevées par un outil de m..

Le tool s’utilise pour l’instant en standalone, donc il faut passer le MoRef de la VM en argument (ou je sais c’est moyen, mais bon, c’est du C++ !). Il prend les arguments suivants :

lazyMethodEnabler.exe -host 10.69.69.69 -user "vmdude" -password "esxi4ever" -vm "moid=vm-69"
  • -host <host IP> : IP du serveur vCenter
  • -user <vcenter Username> : nom d’utilisateur pour se connecter au vCenter
  • -password <vcenter Password> : mot de passe de l’utilisateur
  • -vm « moid=moref » : MoRef de la machine virtuelle

Il existe un argument optionnel supplémentaire -disableMethods qui permet de forcer la désactivation de la méthode RelocateVM_Task. Au final, cette opération n’effectue que l’appel VixDiskLib_PrepareForAccess() (c’est à dire sans terminer par un appel à VixDiskLib_EndAccess() ) et permettra de « simuler » une VM avec le problème.

Attention, l’argument -disableMethods n’est à utiliser qu’en cas de debug !

Les sources Visual Studio 2012 (Visual C++) sont disponibles ici :

lazyMethodsEnabler.zip : exécutable uniquement

lazyMethodsEnabler-VDDK.zip : exécutable + librairies VDDK5.0

lazyMethodsEnabler-Sources.zip : Sources Visual C++

Comme l’outil se base sur des appels VDDK, il faut que le SDK soit installé sur le PC qui lancera lazyMethodEnabler. Les tests ont été réalisé avec VDDK 5.0 (disponible ici : http://www.vmware.com/download/download.do?downloadGroup=VDDK50U2) sur un serveur Windows 2008 R2.

PS: Désolé Samir d’avoir mis aussi longtemps pour publier ce billet :p Mea Culpa !

Viva la HashTable

On a toujours essayé d’optimiser au maximum les scripts et applications que l’on développait, car dès le moment que l’infrastructure est relativement importante, le gain est loin d’être négligeable (on l’a vu précédemment avec les optimisations sur le vCheck).

En se creusant la tête pour diminuer le temps d’exécution d’un script (ou plutôt d’un OneLiner), on a trouvé une nouvelle piste pour l’optimisation de vos scripts, un peu dans le même esprit que le NoSQL, à savoir se baser sur une association clé-valeur plutôt qu’un schéma relationnel complexe.

Pour cela, on va utiliser des hashtables que l’on va peupler au début du script et utiliser par la suite. La structure HashTable est très utile lors des recherches, car son cout en accès est très faible, en moyenne O(1) en notation BigO (aka ça envoie) :

Pour l’exemple, on avait un OneLiner relativement simple qui consistait à lister les machines virtuelles et leur cluster qui n’étaient pas dans un ressource pool (donc qui avaient comme parent le ressource pool ‘Resources’, un peu plus d’explication à la page 43 du document de gestion de ressource de VMware) :

get-view -ViewType virtualmachine -Property ResourcePool, Name | ?{(Get-View $_.ResourcePool -Property Name).Name -eq "Resources"} | Select @{n="Cluster";e={(get-view (Get-View $_.ResourcePool -Property Parent).Parent -Property Name).Name}}, Name

Ce OneLiner filtre déjà tous les appels Get-View pour minimiser le temps d’exécution mais prenait quand même pas mal de temps…

On a donc essayé de voir ce qu’on pouvait faire avec les hashtables. On a donc créé plusieurs hashtables afin de ne plus avoir aucun appel Get-View à part bien sûr le premier récupérant les machines virtuelles).

$htabResourcePool = @{}
$htabResourcePoolParent = @{}
$htabCluster = @{}

Une fois déclarées, on a peuplé ces hashtables avec les valeurs dont on avait besoin (en utilisant le MoRef pour la clé) :

get-view -viewtype resourcepool -property name -Filter @{"name"="Resources"} | %{$htabResourcePool.Add($_.MoRef,$_.Name)}
get-view -viewtype resourcepool -property parent -Filter @{"name"="Resources"} | %{$htabResourcePoolParent.Add($_.MoRef,$_.Parent)}
get-view -viewtype clustercomputeresource -property name | %{$htabCluster.Add($_.MoRef,$_.Name)}

On pourra ensuite les utiliser directement dans le OneLiner en remplaçant les appels Get-View par des opérations de recherches dans les hashtables :

get-view -ViewType virtualmachine -Property ResourcePool, Name | ?{$htabResourcePool[$_.ResourcePool] -eq "Resources"} | Select @{n="Cluster";e={$htabCluster[$htabResourcePoolParent[$_.ResourcePool]]}}, Name

Pour l’instant, on est au même niveau de résultats que la méthode sans les hashtables, mais il faut se poser la question du temps d’exécution :p

Pour cela, on a créé un script qui va exécuter les 2 traitements :

  1. la première méthode en récupérant via des appels Get-View
  2. la deuxième méthode en peuplant des hashtables et en les utilisant par la suite (le remplissage des hashtables faisant intégralement parti du test pour être réellement dans le même périmètre).

Le script affichera le nombre de résultat des 2 méthodes (afin de s’assurer que le contenu retourné est bien identique) et le temps pris. Dans notre exemple, nous avions un peu moins de 2200 VMs sur la plateforme interrogée et les résultats parlent d’eux-mêmes :

Pour ne pas se mettre à dos hypervisor.fr qu’on entend crier d’ici « Toucher pas à mon OneLiner! », l’exemple choisi est effectivement très parlant car il y a des imbrications d’appels Get-View donc le passage à des hashtables sera d’autant plus efficace :p

Il se peut donc que suivant le script, le gain de l’utilisation des hashtables ne soient pas aussi flagrant. Cependant, on vous invite à faire le test et comparer les temps d’exécution afin de vous faire un avis.

Voici le script utilisé pour effectuer les tests avec les 2 méthodes :

Write-Host -ForegroundColor Yellow "Benchmarking starting..."

Write-Host "`nMethod 1 (with regular filtered Get-View)"
$startMethod1 = Get-Date
$resultMethod1 = get-view -ViewType virtualmachine -Property ResourcePool, Name | ?{(Get-View $_.ResourcePool -Property Name).Name -eq "Resources"} | Select @{n="Cluster";e={(get-view (Get-View $_.ResourcePool -Property Parent).Parent -Property Name).Name}}, Name
$endMethod1 = Get-Date

Write-Host -ForegroundColor Green "Found"(($resultMethod1 | Measure-Object).Count)"records in"(($endMethod1 - $startMethod1).TotalSeconds)"seconds"

Write-Host "`nMethod 2 (with hashtable)"
$startMethod2 = Get-Date
$htabResourcePool = @{}
$htabResourcePoolParent = @{}
$htabCluster = @{}

get-view -viewtype resourcepool -property name -Filter @{"name"="Resources"} | %{$htabResourcePool.Add($_.MoRef,$_.Name)}
get-view -viewtype resourcepool -property parent -Filter @{"name"="Resources"} | %{$htabResourcePoolParent.Add($_.MoRef,$_.Parent)}
get-view -viewtype clustercomputeresource -property name | %{$htabCluster.Add($_.MoRef,$_.Name)}

$resultMethod2 = get-view -ViewType virtualmachine -Property ResourcePool, Name | ?{$htabResourcePool[$_.ResourcePool] -eq "Resources"} | Select @{n="Cluster";e={$htabCluster[$htabResourcePoolParent[$_.ResourcePool]]}}, Name
$endMethod2 = Get-Date

Write-Host -ForegroundColor Green "Found"(($resultMethod2 | Measure-Object).Count)"records in"(($endMethod2 - $startMethod2).TotalSeconds)"seconds"