Accueil > SRM > Exécution de scripts dans les VMs avec SRM
Août/1113

Lors de la mise en place de PRA avec VMware Site Recovery Manager, il est plus qu’utile mettre en place des routines pour vérifier que les services applicatifs contenu sont bien repartis. Pour cela le produit inclut la possibilité de lancer des scripts, cependant si les commandes des scripts sont passées à travers le réseau elles sont incompatible avec le mode « Test » de SRM. En effet, lors du mode « Test », les VMs sont démarré dans un réseau isolé qui ne peut communiquer avec le serveur SRM qui doit lancer les scripts. Il est alors impossible de vérifier le bon fonctionnement des scripts.

Il y a cependant une solution: c’est d’utiliser VIX pour demander à la couche de virtualisation de lancer un script local aux VMs. Cette fonction est disponible en PowerCLI avec le cmdlet Invoke-VMScript. Pour info, cette partie sera intégré dans la prochaine version: SRM5.

Je vais donc présenter un exemple de lancement de scripts pour réaliser cela à l’étape « Post Power-On » des VMs. Il faut faire appel à plusieurs scripts qui en appel d’autres, l’important est d’être capable de récupérer les codes retour d’erreurs entre les différents contextes pour qu’ils soient prises en compte comme résultat par SRM.

Pour commencer, voici un synopsis de la communication en différents scripts et le traitement des codes retour:

Quelques considérations avant d’entrer dans les scripts:

  • Les serveurs SRM sont installés localement au serveur vCenter de chaque site, ainsi que PowerCLI (avec l’option VIX) est installé sur chaque vCenter.
  • Les scripts locaux doivent être appelé avec un compte ayant suffisamment de droit dans la VM. Pour des raisons évidentes de sécurité, on ne va pas stocker les mots de passe en clair dans les scripts mais de façon chiffrer dans un fichier qui sera appelé en PowerCLI.
  • Les commandes et les scripts sont lancés par le compte de service de SRM. Le fichier credentials.xml doit donc être peuplé avec le même compte pour que les scripts puissent y accéder.
  • Les scripts sur le serveur SRM sont écrits de façon à tourner sur les 2 serveurs SRM. Pour assurer le Failback, ils devront être copiés sur les 2 serveurs SRM.
  • Les scripts locaux aux VMs doivent porter le même nom mais ils sont spécifique à chaque VM. Rien à modifier pour le Failback.
  • Le fichier credentials.xml est chiffré par rapport à chaque serveur SRM, il ne peut être copié sur l’autre serveur SRM. Pour assurer le Failback il doit être peuplé sur les 2 serveurs SRM.
  • Pas besoin de réseau en mode test, mais si vous utilisez un compte de domaine, il faut quand même s’être connecter au moins une fois avec le compte en question.

D’abord, il faut définir le lancement d’un script bat à la phase « Post Power-On » d’une VM. Pour cela, il faut aller dans le « Protection Group » sur le serveur SRM du site principal. Dans l’onglet « Virtual Machines« , sélectionner une VM et faire un « Configure Protection« . A l’étape « Post Power On », cliquer sur « Add Command » et renseigner la commande c:windowssystem32cmd.exe /C « C:Scripts_SRMvmpostpoweron.bat » comme-ci dessous:

Ensuite, aller sur l’autre serveur SRM, sélectionner votre Recovery Plan et aller dans l’onglet « Recovery Steps« . En dépliant les étapes « Recover » des VMs, on retrouve notre commande lancée au Post Power-On d’une VM, comme ci-dessous:

La commande fait appel au script batch vmpostpoweron.bat. en se basant sur les variables %VMware_RecoveryMode% & %VMware_VM_Name% on récupère le mode d’éxécution du RecoveryPlans et le nom de la VM pour laquelle le script est lancé (cf. tableau 5 page 51 de la doc d’admin SRM).

Le début du script affiche des messages dans le fichier de logs comme le mode d’exécution SRM. Ensuite, il appelle le script postpoweron.ps1 en PowerCLI avec en paramètre le nom de la VM et le mode d’exécution. En plus, on a la commande exit $LASTEXITCODE qui permet de retourner le résultat du script PowerCLI vers la variable %errorlevel% au niveau du batch. Le batch termine par un exit du code retour pour qu’il soit renvoyé à SRM.

vmpostpoweron.bat :
@echo off
echo ------------------------------------------------ >> C:scripts_SRMSRM_scripts.log
echo --- Script %0 started on %date% at %time% >> C:scripts_SRMSRM_scripts.log
 
if "%VMware_RecoveryMode%"=="test" goto test
if "%VMware_RecoveryMode%"=="recovery" goto recovery
echo -- Variable "VMware_RecoveryMode" unset >> C:scripts_SRMSRM_scripts.log
goto end
 
:test
echo Running Post-PowerOn script for %VMware_VM_Name% in TEST mode >> C:scripts_SRMSRM_scripts.log
goto run
 
:recovery
echo Running Post-PowerOn script for %VMware_VM_Name% in RECOVERY mode >> C:scripts_SRMSRM_scripts.log
goto run
 
:run
C:WINDOWSsystem32windowspowershellv1.0powershell.exe -psc "C:Program FilesVMwareInfrastructurevSphere PowerCLIvim.psc1" -command "&{C:scripts_SRMpostpoweron.ps1 -VM %VMware_VM_Name% -Mode %VMware_RecoveryMode%};exit $LASTEXITCODE" >> C:scripts_SRMSRM_scripts.log
set coderetour=%errorlevel%
goto end
 
:end
echo CodeRetour: %coderetour% >> C:scripts_SRMSRM_scripts.log
echo --- Script %0 ended on %date% at %time% >> C:scripts_SRMSRM_scripts.log
exit /b %coderetour%

Le script PowerCLI postpoweron.ps1 (appelé par vmpostpoweron.bat) récupère les paramètres du mode de la VM et du mode d’éxécution SRM. Il se connecte au vCenter en basant sur le hostname (exécution locale au vCenter de chaque site). Puis il récupère les crédentials pour la connexion à la VM dans le fichier credentials.xml. Ensuite, il regarde si la VM est Windows ou Linux en se basant sur le début du nom du Guest OS. En fonction de cela il exécute un script batch postpoweron.bat (pour une VM Windows) ou un script bash postpoweron.sh (pour une VM Linux) localement dans la VM avec les crédentials récupérés précédemment. Le résultat du script dans la VM est enregistré dans $exitcode alors que le résultat du cmdlet Invoke-VMscript est dans $?. La variable $? est égale à faux si les crédentials ou le script n’est pas présent dans la VM, dans ce cas il retour 99 comme code retour. Enfin, il se déconnecte du vCenter et renvoie le

postpoweron.ps1 :
Param($VM,$Mode)
$VC = hostname
$VC = $VC+".domain.local"
 
# Connexion au vCenter local au site
Connect-VIServer -Server $VC -WarningAction SilentlyContinue
 
# Lecture des Credentials dans le fichier credentials.xml
$creds = Get-VICredentialStoreItem -Host $VM -File "C:scripts_SRMcredentials.xml"
 
Write-Host "PS pour la VM $VM en mode $Mode"
# Lecture de l'OS pour le type de scrip a lancer
If ($(get-VMGuest -VM $VM).OSFullName.StartsWith("Microsoft") -eq $True) {
   # Lancement du script C:scripts_SRMpostpoweron.bat avec les credentials et le mode en parametre
   Write-Host "Invoke-VMScript: C:Scripts_SRMpostpoweron.bat $Mode"
   $exitcode=Invoke-VMScript -VM $VM -ScriptText "C:scripts_SRMpostpoweron.bat $Mode" -GuestUser $creds.User -GuestPassword $creds.Password -ScriptType bat
} else {
   # Lancement du script /scripts_SRM/postpoweron.sh avec les credentials et le mode en parametre
   Write-Host "Invoke-VMScript: /Scripts_SRM/postpoweron.sh $Mode"
   $exitcode=Invoke-VMScript -VM $VM -ScriptText "/scripts_SRM/postpoweron.sh $Mode" -GuestUser $creds.User -GuestPassword $creds.Password -ScriptType bash
}
If ($? -eq $False) {$exitcode=99}
 
Disconnect-VIServer -Server $global:DefaultVIServers -confirm:$FALSE
Exit $exitcode

Les scripts locaux aux VMs qu’ils soient pour Windows ou Linux ont à peu près la même structure. Ici dans nos exemples, la structure prend en compte la différence entre les 2 modes d’éxécution SRM (test ou recovery) mais l’éxécution est le même. Ensuite, effectue 3 taches facilement modifiale: il démarre un service, il vérifie que le service est en cours d’éxécution et il vérifie qu’un processus est lancé. Pour renvoyé le code retour, on fait un echo du code retour pour qu’il soit interprété par le script PowerCLI (la commande exit n’est pas traitée).

postpoweron.sh :
case $1 in
test|recovery )
  service ntpd start | grep "OK" > /dev/null 2>&1
  exitcode=$?
  if [ $exitcode != "0" ]
  then
    echo $exitcode
	exit 1
  fi
  service ntpd status | grep "running" > /dev/null 2>&1
  exitcode=$?
  if [ $exitcode != "0" ]
  then
    echo $exitcode
	exit 1
  fi
    ps ax | grep "ntpd" | grep -v grep > /dev/null 2>&1
  exitcode=$?
  if [ $exitcode != "0" ]
  then
    echo $exitcode
	exit 1
  fi
;;
* )
  echo 99
  exit 1
;;
esac
 
echo 0
postpoweron.bat :
@echo off
if "%1"=="test" goto test
if "%1"=="recovery" goto recovery
set ERRORLEVEL=1
goto erreur
 
:test
:recovery
net start "Print Spooler" > NUL 2>&1
if %ERRORLEVEL% NEQ 0 goto erreur
sc query "Print Spooler" | findstr /c:RUNNING > NUL 2>&1
if %ERRORLEVEL% NEQ 0 goto erreur
tasklist | findstr /c:spoolsv.exe > NUL 2>&1
if %ERRORLEVEL% NEQ 0 goto erreur
goto fin
 
:erreur
echo %ERRORLEVEL%
exit /b 1
 
:fin
echo 0
exit /b 0

Les scripts locaux aux VMs sont bien sur à adapter en fonction du besoin, ici c’est surtout un exemple de structure facilement adaptable.

Et voila: lorsque que tout se passe bien on a le résultat suivant dans SRM:

Et lorsqu’il y a une erreur, l’information remonte bien dans SRM mais le Recovery Plan n’est pas arrêté pour autant:

En complément d’information, je rajouterai une partie sur les scripts permettant de peupler le fichier credentials.xml. Comme expliqué au début, les scripts sont lancés avec le compte SRM pour pouvoir lire le fichier, il faut qu’il soit également créé avec ce compte. Dans le fichier add-credential.bat, on fait un RunAs pour lancer le script PowerCLI avec le compte de service pour SRM.

add-credential.bat :
@echo off
echo Script to Add Credentials for a VM
runas /user:DOMAINsrm_srvc "C:WINDOWSsystem32windowspowershellv1.0powershell.exe -psc "C:Program FilesVMwareInfrastructurevSphere PowerCLIvim.psc1" -command "^&{C:scripts_SRMadd-credential.ps1}" >> SRM_scripts.log"

Le script add-credential.ps1 est un détournement des fonctions *-VICedentialStoreItem normalement faites pour stocker les mots de passe des serveurs ESX. Les particularités sont que pour les comptes utilisateurs sans domaine (exemple les comptes Linux) il faut retirer le et pour traiter le mot de passe il faut convertir le format. Le script ne fait que de l’ajout au fichier credentials.xml, il ne remplace pas les crédentials déjà existants dans le fichier.

add-credential.ps1 :
# Questions sur le nom de la VM et ses credentials
$VM = Read-Host "Nom de la VM"
$VM = $VM.Trim()
Write-Host "Entrer les credentials pour cette VM"
$creds = Get-Credential
# Supression du "" s'il n'y a pas de nom de domaine
if ($creds.Username[0] -eq "") {$User = $creds.Username.replace("","")} else {$User = $creds.Username}
# Conversion du format du password
$passwd = [System.Runtime.InteropServices.Marshal]::PtrToStringUni([System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($creds.Password))
# Stockage de facon chiffre dans le fichier credentials.xml
New-VICredentialStoreItem -Host $VM -User $User -Password $passwd -File "C:scripts_SRMcredentials.xml"

Et pour finir quelques ressources intéressantes:

  1. 02/01/2012 à 12:32 | #1

    Ici un bon script de LucD pour valider les pré-requis Invoke-VMscript:
    http://www.lucd.info/2012/01/01/will-invoke-vmscript-work/

  1. Pas encore de trackbacks