Clonage de machine virtuelle

De Wiki de Jordan LE NUFF
Sauter à la navigation Sauter à la recherche

Présentation

Cette page a pour objet de montrer comment cloner des machines virtuelles à partir de PowerCLI.

Prérequis

Simple clonage

Script

Voici un script nommé vmware_clone_VM.ps1 qui permet de cloner une machine vers une autre :

#!/usr/bin/pwsh

# Penser à utiliser le script create_credentials.ps1 pour créer les credentials

<#
.SYNOPSIS
    Script pour exporter une VM depuis le vCenter
.DESCRIPTION
    Au préalable, enregistrer les credentials en lançant le script create_credentials.ps1
.PARAMETER VmNameSource
    Le nom de la VM à cloner. (obligatoire)
.PARAMETER VmNameTarget
    Le nom de la VM cible à créer par clonage. (obligatoire)
.PARAMETER VmHostNameTarget
    Le nom de l'ESXi qui hébergera la VM cible. (faculatif)
	Si absent, prendra la valeur de l'ESXi source.
.PARAMETER VmDatastoreNameTarget
    Le nom du datastore qui hébergera la VM cible. (faculatif)
	Si absent, prendra la valeur du datastore source.
	Si fourni, doit correspondre à un datastore de l'ESXi $VmHostNameTarget.
.PARAMETER VmLocationTarget
    Le dossier de VM dans lequel se trouvera la VM cible. (faculatif)
	Seul le nom du dossier sans son arborescence est attendu.
	Ainsi, si un nom de dossier existe plus d'une fois, le script s'arrêtera.
	Si absent, prendra la valeur du dossier de VM source.
.PARAMETER VmDescriptionTarget
    Description de la VM cible. (faculatif)
.PARAMETER DeleteTarget
    Confirmation de la suppression de la VM cible avant clonage si elle existe. (faculatif)
	Valeur possible : No ou Yes
	Si Yes, la VM cible est définitivement supprimée.
	Si No et si la VM cible n'existe pas, le script s'exécutera normalement et la VM cible sera créée.
	Si No et si la VM cible existe déjà, le script se terminera immédiatement sans réaliser le clonage.
.EXAMPLE
	./vmware_clone_VM.ps1 -DeleteTarget Yes myserver mybackupserver
.NOTES
    Author: LE NUFF Jordan
    Date:   Jan 11, 2021
#>

## Définition des paramètres d'entrée
Param
(
	[Parameter(Mandatory=$true, Position=0, HelpMessage="Nom de la VM source")]
	[string]$VmNameSource,
	[Parameter(Mandatory=$true, Position=1, HelpMessage="Nom de la VM cible")]
	[string]$VmNameTarget,
	[Parameter(Mandatory=$false, HelpMessage="ESXi cible")]
	[string]$VmHostNameTarget,
	[Parameter(Mandatory=$false, HelpMessage="Datastore cible")]
	[string]$VmDatastoreNameTarget,
	[Parameter(Mandatory=$false, HelpMessage="Dossier de VM cible")]
	[string]$VmLocationTarget,
	[Parameter(Mandatory=$false, HelpMessage="Description de VM cible")]
	[string]$VmDescriptionTarget="",
	[Parameter(Mandatory=$false, HelpMessage="Confirmation de la suppression de la VM cible : No ou Yes")]
	[ValidateSet('No','Yes')]
	[string]$DeleteTarget='No'
)
If ($VmNameSource -eq $VmNameTarget) {
	Write-Host "La VM cible ne peut pas être la même que la VM source '$VmNameSource'. Fin du script."
	exit
}

## Initialisation variables
# Dossier des identifiants
$CredsFileLocation="/data/scripts/.credentials"
# Adresse IP du vCenter
$UrlVcenter="vcenter01.groupegdb.local"
# Identifiant VMware à utiliser
$VmwareUser="expl@groupegdb.local"
# Construction du fichier d'identifiants à utiliser
$VcFileCreds=$($CredsFileLocation + "/" + $UrlVcenter + "_" + $VmwareUser + "_ps.xml")
# Importation des credentials
$VcCreds=Import-Clixml -Path $VcFileCreds

## Connection au VCenter
Connect-VIServer -Server $UrlVcenter -Credential $VcCreds | Out-Null

## Vérifications
# La VM source existe-t-elle ? Si non, fin du script
$VmSource=Get-VM -name $VmNameSource -ErrorAction SilentlyContinue
If (!$VmSource){
	Write-Host "La VM source $VmNameSource n'existe pas. Fin du script."
	exit
} ElseIf ($VmSource.Count -gt 1) {
	Write-Host "La VM source $VmNameSource fournie existe plus d'une fois. VM source ambigüe. Fin du script."
	exit
}
# La VM cible existe-t-elle ? Si oui et absence de la confirmation de la suppresion, fin du script
$VmTarget=Get-VM -name $VmNameTarget -ErrorAction SilentlyContinue
If ($VmTarget) {
	If ($VmTarget.Count -gt 1) {
		Write-Host "La VM cible $VmNameCible fournie existe plus d'une fois. VM cible ambigüe. Fin du script."
		exit
	} ElseIf ($DeleteTarget -eq 'No') {
		Write-Host "La VM cible $VmNameTarget existe et sa suppression n'a pas été confirmée en entrée de ce script avec l'option '-DeleteTarget Yes'. Fin du script."
		exit
	}
	If ( $VmTarget.PowerState -ne 'PoweredOff' ) 
	{
		$counter = 0
		Shutdown-VMGuest $VmNameTarget -confirm:$false | Out-Null
		do {
			Start-Sleep -s 1
			If ( $counter -ge 60 ) {
				Write-Host "La VM cible $VmNameTarget n'est toujours pas éteinte après un délai de 60 secondes. Fin du script."
				exit
			}
			$VmTarget = Get-VM $VmNameTarget
			$status = $VmTarget.PowerState
			$counter++
		} until ($status -eq "PoweredOff")
	}
}
# Si l'ESXi cible a été fourni, vérification de son existence
If ($VmHostNameTarget) {
	$VmHostTarget=Get-VMhost -Name $VmHostNameTarget -ErrorAction SilentlyContinue
	# Si inexistant, fin du script
	If (!$VmHostTarget){
		Write-Host "L'ESXi cible $VmHostNameTarget fourni n'existe pas. Fin du script."
		exit
	}
# Si l'ESXi n'a pas été fourni
} ElseIf (!$VmHostNameTarget) {
	# Utilisation du même ESXi que la VM source
	$VmHostTarget=Get-VMhost -VM $VmSource
}
# Si le datastore a été fourni, vérification de son existence
If ($VmDatastoreNameTarget) {
	$VmDatastoreTarget=Get-Datastore -Name $VmDatastoreNameTarget -ErrorAction SilentlyContinue
	# Si inexistant, fin du script
	If (!$VmDatastoreTarget){
		Write-Host "L'ESXi cible $VmDatastoreNameTarget fourni n'existe pas. Fin du script."
		exit
	# Si existant
	}
# Si le datastore n'a pas été fourni
} ElseIf (!$VmHostNameTarget) {
	# Utilisation du même ESXi que la VM source
	$VmDatastoreTarget=Get-Datastore -VM $VmSource
}
# Si le datastore cible n'est pas accessible depuis l'ESXi cible, fin du script
If (!$(Get-Datastore -VMHost $VmHostTarget | Where-Object {$_ -eq $VmDatastoreTarget})){
	Write-Host "Le datastore cible $VmDatastoreTarget n'est pas accessible depuis l'ESXi cible $VmHostTarget. Fin du script."
	exit
}
# Si le dossier de VM cible a été fourni, vérification de son existence
If ($VmLocationTarget) {
	$LocationTarget=Get-Folder -Name $VmLocationTarget -Type VM -ErrorAction SilentlyContinue
	# Si inexistant, fin du script
	If (!$LocationTarget){
		Write-Host "Le dossier de VM cible $VmLocationTarget fourni n'existe pas. Fin du script."
		exit
	} ElseIf ($LocationTarget.Count -gt 1) {
		Write-Host "Le dossier de VM cible $VmLocationTarget fourni existe plus d'une fois. Localisation cible ambigüe. Fin du script."
		exit
	}
# Si le dossier de VM cible n'a pas été fourni
} ElseIf (!$VmHostNameTarget) {
	# Utilisation du même dossier de VM que la VM source
	$LocationTarget=Get-Folder -Id $VmSource.FolderId
}

## Traitement
# Suppression de la VM cible
If ($VmTarget -And $DeleteTarget -eq 'Yes') {
	Write-Host "Suppression de la VM cible $VmTarget"
	Remove-VM -VM $VmTarget DeletePermanently confirm:$false
	Write-Host "La VM $VmTarget a été supprimée avec succès."
}
# Clonage de la machine
If (New-VM -Name $VmNameTarget -VM $VmSource -VMHost $VmHostTarget -Datastore $VmDatastoreTarget -Location $LocationTarget -Description $VmDescriptionTarget) {
	Write-Host "La VM $VmNameTarget a été clonée avec succès depuis la VM $VmSource. Fin du script."
} Else {
	Write-Host "Une erreur est survenue lors du clonage de la VM $VmNameTarget depuis la VM $VmSource Fin du script."
	exit
}

Disconnect-VIServer -Confirm:$false

Utilisation

L'utilisation de ce script se fait de la façon suivante :

./vmware_clone_VM.ps1 [-VmNameSource] <string[]> [-VmNameTarget] <string[]> [-VmHostNameTarget <String>] [-VmDatastoreNameTarget <String>] [-VmLocationTarget <String>] [-VmDescriptionTarget <String[""]>] [-DeleteTarget <String["No"|"Yes"]="No">]

Voici le détail des options :

  • VmNameSource
Le nom de la VM à cloner. (obligatoire)
  • VmNameTarget
Le nom de la VM cible à créer par clonage. (obligatoire)
  • VmHostNameTarget
Le nom de l'ESXi qui hébergera la VM cible. (faculatif)
Si absent, prendra la valeur de l'ESXi source.
  • VmDatastoreNameTarget
Le nom du datastore qui hébergera la VM cible. (faculatif)
Si absent, prendra la valeur du datastore source.
Si fourni, doit correspondre à un datastore de l'ESXi $VmHostNameTarget.
  • VmLocationTarget
Le dossier de VM dans lequel se trouvera la VM cible. (faculatif)
Seul le nom du dossier sans son arborescence est attendu.
Ainsi, si un nom de dossier existe plus d'une fois, le script s'arrêtera.
Si absent, prendra la valeur du dossier de VM source.
  • VmDescriptionTarget
Description de la VM cible. (faculatif)
  • DeleteTarget
Confirmation de la suppression de la VM cible avant clonage si elle existe. (faculatif)
Valeur possible : No ou Yes
Si Yes, la VM cible est définitivement supprimée.
Si No et si la VM cible n'existe pas, le script s'exécutera normalement et la VM cible sera créée.
Si No et si la VM cible existe déjà, le script se terminera immédiatement sans réaliser le clonage.

Limitations

A ce jour, ce script possède des limitations liées aux noms qui existent en double.

Cela concerne les objets suivants :

  • Machine Virtuelle
Deux machines virtuelles peuvent porter le même nom. En revanche, leurs ID seront différents. Ce script se basant sur le nom d'une machine virtuelle, il tombera en erreur et s'arrêtera en cas de machine non-unique.
  • Dossier de VM
Un dossier de VM est défini par
  • Un ID et nom
  • Un ID de parent
Ainsi, l'arborescence d'un dossier n'est pas inclus dans son nom. De ce fait, il n'est pas possible d'indiquer un chemin complet en entrée de ce script. De la même manière que pour les machines virtuelles, Deux dossiers de VM peuvent porter le même nom. Ainsi, le script tombera en erreur et s'arrêtera en cas de dossier de VM non-unique.

Clonage multiple

Prérequis

  • Script vmware_clone_VM.ps1 présenté plus haut
  • Fichier CSV contenant les informations nécessaires des machines à cloner

Fichier CSV

Voici un exemple de fichier CSV : Le fichier vmlist est manquant.

VmSource VmHostnameSource IpSource GwSource VmTarget IpTarget GwTarget ESX Datastore Dossier VLAN Utilisateur Description