Voici le script que j’utilise en ce moment pour les mises en maintenance des hôtes AHV des clusters Nutanix avec un menu à choix multiples :


Disconnect-NTNXCluster *

#Choisir le cluster 
$ClusterNut = Read-Host "Entrer the Ip or DNS name of your Nutanix Cluster to manage"

Connect-NTNXCluster $ClusterNut -AcceptInvalidSSLCerts -ForcedConnection
$Clusterlist = $null


for () {

# récupère la liste des noms d'hôtes du cluster
$Clusterlist = Get-NTNXHost

    #défini integer à 0
    $i=0

    $ClusterName = (Get-NTNXCluster).name

    Write-Host "Vous avez selectionné le cluster $($(Get-NTNXCluster).name)
    "

    # Créer un menu : Pour chaque hôte du cluster ajouter 1 à i et afficher le nom d'hôte associé
    write-host "0 : Sortir du script"
    foreach ($ht in $Clusterlist) {
        $i++
        Write-Host "$i : $($ht.Name) : état  $($ht.hypervisorState) : Hyperviseur $($ht.hypervisorAddress) : IPMI $($ht.ipmiAddress) " 
        }

    do {
    $Menu = Read-Host "Choisir le numéro d'hôte"
    #juste affichage : tant que le chiffre indiqué n'est pas un nombre d'un hôte possible on boucle ici
    if (0..$Clusterlist.Count -notcontains $Menu) {Write-Host "Merci d'indiquer le numéro correspond au noeud à mettre en maintenance" -ForegroundColor Red}
    }

    #tant que le chiffre indiqué n'est pas un nombre d'un hôte possible on boucle ici
    while (0..$Clusterlist.Count -notcontains $Menu)

    #Conserve le nom de l'hôte dans la variable ChoiceMenu le -1 sert car le count debute à 0.
    if ($menu -eq 0) {
                        #Déco
                        Disconnect-NTNXCluster *
                        exit
                      } 
    $ChoiceMenu = ($Clusterlist).name[$menu-1]
    write-host "Vous avez choisi le $ChoiceMenu"

    Write-Host -ForegroundColor Green "Choisir l'option 1 pour Mettre en Maintenance et l'option 2 pour remettre en ligne" 
    $Menu1 = Read-Host 

    if ($Menu1 -eq 1) {
        $uuid = (Get-NTNXHost | where {$_.name -like $ChoiceMenu}).uuid
        
        write-host "La tache de mise en maintenance de l'hôte $ChoiceMenu est en cours"
        Start-NTNXMaintenanceMode -Hostid $uuid -EvacuationOption LIVE_MIGRATE
        sleep 3 
        
    }

    if ($Menu1 -eq 2) {
    write-host "La tache remise en prod de l'hôte $ChoiceMenu est en cours"
    Stop-NTNXMaintenanceMode -Hostid $uuid
    sleep 3
    }
    
}

Vous avez configuré votre sauvegarde locale, mais votre collège Citrix préféré supprime et provisionne sans cesse de nouvelles VDI persistantes :

Je passe la partie authentification, mais voici quelques lignes pour ajouter automatiquement toutes nouvelles machines à la sauvegarde existante (avec le nom LocalBackup) et supprimer de la sauvegarde les machines qui ne seraient plus disponibles.

 

Détermine la liste des VMs qui ne sont pas des CVM et qui ne sont pas
# dans un ProtectionDomain, c'est l'endroit idéal pour exclure des machines
# qui ne seraient pas à ajouter comme les CVM ou d'autres VMs si votre
# convention de nommage permet de les identifier facilement.
$UnProtectedVMs =  (get-ntnxvm | where {$_.vmName -notlike "*CVM*"} | where {$_.ProtectionDomainName -like $null}).vmname

#Ajout les machines non protégées à la sauvegarde
foreach ($VM in $UnProtectedVMs){
    echo "VM à protéger : $VM"
    Add-NTNXProtectionDomainVM -name LocalBackup -names $VM -Consistencygroupname $VM
}

#Determine la liste des VMs protégées dans le dernier snapshot
$ProtectedVMs = (Get-NTNXProtectionDomainSnapshot | Sort-Object Snapshotid | select -last 1).ConsistencyGroups

#determine la liste des VMs hébergées sur le cluster Nutanix
$VMList = (get-ntnxvm | where {$_.vmName -notlike "*CVM*"}).vmname

#Compare la liste complète des VMs à la liste des VMS protégées et conserve les protégées qui n'existent plus
$VMstoRemove = (Compare-Object -DifferenceObject $VMList -ReferenceObject $Protectedvms | where {$_.Sideindicator -like "<="}).InputObject

#Supprime les $VMtoRemove du ProtectionDomain
foreach ($VMtoRemove in $VMstoRemove){
    Remove-NTNXProtectionDomainVM -name LocalBackup -input $VMtoRemove
    echo "VM à supprimer :" $VMtoRemove
}

Nous avions déjà un export automatique vers notre CMDB en place, mais suite à une demande de modification, je me suis dit qu’il était temps de remplacer notre bon vieux get-vm.

Je pensais arriver à un meilleur résultat, mais les requêtes pour le Datacenter et le Cluster ralentissent vraiment l’exécution, malgré ça, l’ancien script prenait 2h55, le nouveau 39min soit presque 4.5 fois plus rapide pour le même scope soit 5 vCenters et un peu plus de 2200VMs.

@"

===============================================================================
Description:   Exports VM Informations to CMDB
Usage:         Schedule task on vCenter
===============================================================================

"@
$StartMs = (Get-Date)
0..1000 | ForEach-Object {$i++}

#Standard PowerCli cmdlets
add-pssnapin VMware.VimAutomation.Core

#Renseigner votre/vos vCenter(s) separé par des virgules
Write-Host "Renseigner votre/vos vCenter(s) separé(s) par des virgules"
$vCenters= Read-Host "VCENTER_NAME"
$Path = Read-Host "Path"

#Date
$Date = Get-Date -Format yyyy-MM-dd

Write-Host "Renseigner le chemin d'export du fichier resultat ainsi que le nom du fichier"
$ExportFilePath = Read-host "$Path\$date\Export-CMDB.csv"

$listVM=@("VMName,VMHostname,Datacenter,Powerstate,OS,IPAddress,MacAddress,NetworkName,ToolsStatus,Cluster,NumCPU,MemMb,Datastore,DiskGB,DiskFree")

 Foreach ($vCenter in $vCenters) {
 Connect-VIServer $vCenter

 $VMs = Get-View -ViewType VirtualMachine
 

 
ForEach ($vm in $VMs) {
      $VMName = $vm.Name
      $VMHostname = $vm.Guest.Hostname
      $parentObj = Get-View $vm.Parent
      #while ($parentObj -isnot [VMware.Vim.Datacenter]) {$parentObj = Get-View $parentObj.Parent | select -Unique}
      while ($parentObj -isnot [VMware.Vim.Datacenter]) {$parentObj = Get-View $parentObj.Parent}
      #Boucle et remonte d'un niveau dans l'arborescence jusqu'à trouver le datacenter
      $Datacenter =   $parentObj.Name
      $Powerstate = $vm.Summary.Runtime.PowerState
      $OS = $vm.config.GuestFullName
      $IPAddress = $vm.Guest.Net.IPAddress
      $MacAddress = $vm.Guest.net.MacAddress
      $NetworkName = $vm.Guest.net.Network
      $ToolsStatus = $vm.Guest.ToolsStatus
      ## use UpdateViewData() to populate the linked view, then access said linked view
      $vm.UpdateViewData("Runtime.Host.Parent.Name")
      $Cluster = $vm.Runtime.LinkedView.Host.LinkedView.Parent.Name
      $NumCPU = $vm.Summary.Config.NumCpu
      $MemMb = $vm.Summary.Config.MemorySizeMB
      $Datastore = $vm.Summary.Config.VmPathName.Split()[0].split('[]')
      #le premier split prend la premiere expression, le deuxieme retire les crochets
      $DiskGB = [Math]::Round((($vm.Guest.Disk | Measure-Object -Property Capacity -Sum).Sum / 1GB),2)
      $DiskFree = [Math]::Round((($vm.Guest.Disk | Measure-Object -Property FreeSpace -Sum).Sum / 1GB),2)
      $listVM+=("$VMName,$VMHostname,$Datacenter,$Powerstate,$OS,$IPAddress,$MacAddress,$NetworkName,$ToolsStatus,$Cluster,$NumCPU,$MemMb,$Datastore,$DiskGB,$DiskFree")
      Write-Host "Traitement de la machine $VMName" -ForegroundColor Yellow
      }
Disconnect-VIServer $Vcenter -Force -Confirm:$false
}

$listVM > $ExportFilePath
Write-Host "Creation du Fichier résultat" -ForegroundColor Red


Write-Host "Déconnection des vCenters" -ForegroundColor Gray
#$VC = Disconnect-VIServer * -Confirm:$False

$EndMs = (Get-Date)
Write-Host "Le script s'est executé en  $($EndMs - $StartMs)"

 

Je ne l’avais pas anticipé, mais lors de la suppression d’une VM VDI Côté Xendesktop, le nettoyage du Protection Domain côté Nutanix n’est pas automatique si bien qu’hier j’ai eu un petit warning « Unable to locate VM with name ‘VM_Name and internal ID ‘60069aa8-29d5-2c52-6827-945372df5a5a’ in protection domain ‘ProtectionDomain_Name’.

Capture

Voici le script que j’utilise pour faire le nettoyage :

#Chargement des Addins
Add-PSSnapin Citrix*
Add-PSSnapin Nutanix*

#Renseigner votre broker Xendesktop
$XenBroker = Read-Host "Broker_name"

#Renseigner vos IP CVM Nutanix
$NutanixCluster1 = Read-Host "IP_VCM_Cluster1"
$NutanixCluster2 = Read-Host "IP_VCM_Cluster2"

#Connexion aux clusters Nutanix
Connect-NTNXCluster -Server:$NutanixCluster1 -UserName:admin -AcceptInvalidSSLCerts
Connect-NTNXCluster -Server:$NutanixCluster2 -UserName:admin -AcceptInvalidSSLCerts

#Recupération des VDI Xen
$VDIs=Get-ProvVM -AdminAddress $XenBroker

#Création de la liste des VDI Xen
$XEN_VMs = $VDIs.VMName

#Récuperation de la liste de Protection Domain Nutanix
$NUT_VMs = Get-NTNXPRotectionDomain

#Création de la liste des VM Nutanix
$NUT_VMS = $NUT_VMS.vms.vmName

#Comparaison des deux precedentes listes, conservation des machines présentent côté nutanix, absentent côté Vdi Xendesktop
$VMs2Delete = Compare-Object -ReferenceObject $NUT_VMs -DifferenceObject $XEN_VMs | Where { $_.SideIndicator -eq "<=" }

#Pour chaque VM de cette liste à supprimer, recuperation du Protection Domaine associé et suppression de la VM de celui-ci
foreach ($VM in $VMs2Delete) {
$ProtectionDomain = Get-NTNXProtectionDomain | Where {$_.vms.vmname -like $VM.InputObject}
Remove-NTNXProtectionDomainVM -name $ProtectionDomain.name -input $VM.InputObject
}

#Déco et fin du script
Disconnect-NTNXCluster *

Il y aura un peu de rouge à l’exécution étant donné que le script essayera de supprimer la VM sur les 2 Sites donc pas d’inquiétude.

A la suite de mon précédent article « Nutanix Async DR  with Citrix Xendesktop MCS VDI« , le point a été remonté chez Nutanix et la prochaine mise à jour de la documentation devrait éclaircir les choses la dessus.

J’avais des réplications fonctionnelles, mais une autre limitation du design été en train de me poser problème.

En version 4.5 d’après la doc Nutanix « System Maximums », nous ne pouvons avoir plus de 50 VMs par Protection Domain, consistency group, ou SRA.

Nous avons donc décidé d’automatiser la création des « Protection Domains » de sortent que tous les soirs chaque nouvelle VM soit protégée et répliquée.

Je ne vais pas poster ici le script, car il est vraiment spécifique à notre environnement, mais je vais lister les commandes Nutanix utilisées.

J’ai vraiment eu beaucoup de mal à trouver des exemples et de la documentation pour certaines :

# Création d'un ProtectionDomain
Add-NTNXProtectionDomain -PDName "My_PD"
#Ajout d'une VM à ce Protection Domain
Add-NTNXProtectionDomainVM -PDName "My_PD" -names "My_VM"

Évidemment Attention si vous êtes dans un scenario VDI Xendesktop MCS comme moi, cette commande ne fonctionne que pour synchroniser une machine, les suivantes ne seraient pas dans le bon « Consistency Group »

#Ajout d'une VM à ce Protection Domain avec le meme nom de "Consistency group" 
Add-NTNXProtectionDomainVM -PDName "My_PD" -names "My_VM" -ConsistencyGroupName "My_PD"
#Création d'une tache planifiée associée au précédent Protection Domain
# qui tournera tous les jours à 00:01
Add-NTNXProtectionDomainCronSchedule -Name "My_PD" -Type "DAILY" -EveryNth "1" -UserStartTimeInUsecs "1463522460000000"
#Configuration de la "retention policy"
Set-NTNXProtectionDomainRetentionPolicy -pdname "My_PD" -Id ($(Get-NTNXProtectionDomainCronSchedule -Name "My_PD").Id) -LocalmaxSnapshots 2 -RemoteMaxSnapshots "My_Remote_Site=1"

Je configure donc un snapshot local et un snapshot sur le site de réplication.
Pour la configuration du « RemoteMaxSnapshots » il faut impérativement indiquer le RemoteSite (vous pourriez en avoir plusieurs) coller avec « = » et le nombre de snapshots. 1f616

 

Pour faire le grand nettoyage dans vos configurations de réplication:

#Supprimer tous les snapshots
$snaps=Get-NTNXProtectionDomainSnapshot
foreach ($snap in $snaps){
Remove-NTNXProtectionDomainSnapshot -ProtectionDomainName $Snap.ProtectionDomainName -SnapshotId $Snap.SnapshotId }
#Supprimer toutes les taches planifiées
$PDs = Get-NTNXProtectionDomain
foreach ($PD in $PDs) {
Clear-NTNXCronSchedule -PDname:$PD.name
}
#Sortir toutes les VMs de tous les ProtectionDomains
$VMs = Get-NTNXVM
foreach ($VM in $VMs){
Remove-NTNXProtectionDomainVM -name $VM.protectionDomainName -input $VM.vmName
}

 

Une fois vide les ProtectionDomains devraient être supprimable également:

#Destructions des ProtectionDomains
$PDs = Get-NTNXProtectionDomain
foreach ($PD in $PDs) {
Mark-NTNXProtectionDomainForRemoval -name $PD.name
}

 

 

Concernant l’automatisation, nous avons choisi de reprendre le nom du disque de base Xendesktop dans le nom du « Protection Domain », ainsi que pour le « Consistency Group ».

Cette méthode nous permet de surveiller la limite des 50 machines et nous n’avons qu’un upgrade de l’image de base à réaliser pour faire le découpage.

Vivement l’augmentation de cette limite, car elle est encore administrable dans un petit environnement de quelques centaines de VDI, mais cela deviendrait difficilement compréhensible avec plusieurs milliers.

Si vous avez un autre mode de découpage, ou si vous gérez différemment vos réplications, n’hésitez pas à laisser un message dans les commentaires.

 

J’expliquais dans un précédent article, comment se connecter en powershell au Prism Central pour lancer des commandes comme sur des vCenters en linked-mode.

Il s’avère que c’est une mauvaise idée, bon nombre de cmdlet ne s’exécutent plus avec les messages d’erreurs :

Request is not supported by this cluster.
Le serveur distant a retourné une erreur: (500) Erreur interne du serveur.
 WebException
+ FullyQualifiedErrorId : {« message »: »Request is not supported by this cluster. »}

ntnxerror

Connectez-vous directement sur chacun de vos clusters, cela évitera une bonne perte de temps. emo

Si vous débutez complément, voici les commandes à faire pour se connecter avec un minimum de pré-requis à savoir Powershell et les cmdlet nutanix.

Ce dernier est disponible directement depuis la console Prism dans admin > download Cmdlets Installer.

cmdlet


#chargement des cmdlets
asnp nutanix*

#Connexion sur un noeud du cluster
Connect-NTNXCluster 10.0.0.1 -AcceptInvalideSSLCerts