Backup de máquinas virtuales Hyper-V con Powershell

Artículo destacadoPROYECTO CERO

 

 

El siguiente script de powershell  realiza las siguientes tareas para cada máquina virtual:

  • Guarda el estado de la máquina en una carpeta temporal
  • Restaura la máquina al estado inicial
  • Mueve los ficheros a una ubicación de red sobre-escribiéndolos.

Al final del script  se llama a un comando del sistema llamado robocopy; En este caso, los argumentos de llamada hacen que robocopy mueva los ficheros sobrescribiendo, y borre los archivos existentes en el recurso compartido destino que no están en el origen. A su vez reintentará copiar cada fichero 5 veces esperando 30 segundos en el caso de que haya un fichero cogido por algún proceso.

Hay una opción mas que he colocado, pero no he llegado a probar,  donde  (según la documentación) permite empezar la transferencia cuando la unidad de red está disponible, supongo que a veces la unidad de red puede desaparecer y se puede desconectar de la unidad mapeada.

Sin más dilación, el siguiente script se puede guardar en un fichero llamado BakupitoNas.ps1 y para ejecutarlo desde la consola de powershell  se llama con el comando BakupitoNAS.ps1. Evidentemente faltan algunos retoques, por eso es mejor probarlo y adaptarlo a las necesidades de cada entorno.

##
##    Create a backup of all the vm's
##  and move them to a NAS 

##  Local directory fon temporal operation
$dest = "C:\BackupVM"

##  Network share
$NASDest ="Z:\BackupVM"

$VM_Service = get-wmiobject -namespace root\virtualization Msvm_VirtualSystemManagementService
$ListofVMs = get-wmiobject -namespace root\virtualization Msvm_ComputerSystem -filter  "ElementName <> Name"   

foreach ($Ma in [array] $ListOfVMs)
{
# uncomment to test with one machine
# if(!($Ma.ElementName -eq "W8TFS")){
    $VMReturnState = $Ma.EnabledState
    $VMName = $Ma.ElementName

    if (($Ma.EnabledState -eq 2) -or ($Ma.EnabledState -eq 32768) -or ($Ma.EnabledState -eq 32770))
    {
          $Ma.RequestStateChange(32769)
        echo "Saving the state of $VMName"
    }
    $Ma2 =$Ma
    while (!($Ma2.EnabledState -eq 32769) -and !($Ma2.EnabledState -eq 3))
    {
        Start-Sleep(1)
        $Ma2 = get-wmiobject -namespace root\virtualization -Query "Select * From Msvm_ComputerSystem Where ElementName='$VMName'"
    } 

    if ([IO.Directory]::Exists("$dest\TmpDir\$VMName"))
    {
        [IO.Directory]::Delete("$dest\TmpDir\$VMName", $True)
    }

    echo "Exporting the VM"
    $status = $VM_Service.ExportVirtualSystem($Ma.__PATH, $True, "$dest\TmpDir")
    if ($status.ReturnValue -eq 4096)
    {
        $job = [Wmi]$status.Job    

        while (!($job.PercentComplete -eq 100) -and ($job.ErrorCode -eq 0))
        {
            Start-Sleep(25)
            $job = [Wmi]$status.Job
            echo $job.PercentComplete
        }
    }
    echo "Restoring previous state of $VMName..."
    $Ma.RequestStateChange($VMReturnState)

    echo "Moving files locally..."
    ##    Store the files on in a temp directory before moving them to their location and then remove the old files.
    if ([IO.Directory]::Exists("$dest\$VMName"))
    {
        [IO.Directory]::Move("$dest\$VMName", "$dest\$VMName-OldTmpDir")
        [IO.Directory]::Move("$dest\TmpDir\$VMName", "$dest\$VMName")
        [IO.Directory]::Delete("$dest\$VMName-OldTmpDir", $True)
    }
    else
    {
        [IO.Directory]::Move("$dest\TmpDir\$VMName", "$dest\$VMName")
    }

    echo "Moving files to NAS..."
    robocopy  "$dest\$VMName" "$NASDest\$VMName"  /MIR /MOVE  /R:5 /TBD /NS /NC /NDL /NP
    echo "Done with $VMName"

#uncomment to test With One machine
#}

}