Automating HyperV

El caso de los Checkpoints que no pueden ser eliminados en HyperV

Recientemente se nos presento un caso muy particular. Nos encontramos trabajando en la integración de HP Data Protector 9 para realizar los respaldos de Maquinas Virtuales ejecutadas sobre HyperV 2012 R2. El respaldo es ejecutado de manera exitosa, sin embargo HP DP no elimina los checkpoints generados por la tarea de respaldo (Sigue sin hacerlo, tenemos un caso abierto con HP para realizar la investigación), lo que produce el gran riesgo de que el volumen donde se encuentran las VMs se llene debido a estos Checkpoints no eliminados.

Como buen administrador, y buscando evitar un problema mayor, abro la consola de HyperV Manager dispuesto a eliminar esos molestos Checkpoints. Pero “Oh Sorpresa”, estos Checkpoints no pueden ser eliminados como se hace con uno estandard (incluso el icono que los representa es diferente).

Checkpoint

Aquí surge la pregunta ¿Cómo le hago entonces para deshacerme de estos Checkpoints?

Aqui es donde entra Powershell al rescate. Estos Checkpoints son de un tipo especial llamado “Recovery”, los cuales no puedes ser eliminados desde la consola de Administración de HyperV. Para localizarlos dentro de un Hypervisor, es necesario ejecutar el siguiente comando:

Get-VM | Get-VMSnapshot | where {$_.SnapshotType -eq "Recovery"

Este comando nos dara visibilidad de todos los Checkpoints del tipo “Recovery” que estan aun en las VMs del hypervisor.

Si desean deshacerse de esos molestos Checkpoints, tan solo habria que car uso del Pipe, y mandar la salida haca el comando “Remove-VMSnapshot”:

Get-VMSnapshot | where {$_.SnapshotType -eq "Recovery"} | Remove-VMSnapshot

Ahora bien, si son de los que cuentan con SCVMM y un cluster de Hypervisores y son perezosos como yo para entrar a cada uno de los Hosts y ejecutar el comando, pueden usar el siguiente script.

#Este script se encarga de Revisar todos los Snapshots remanentes de Backups y hace un "merge".
#El script no afecta a los Snapshots regulares.
import-module virtualmachinemanager
$HyperVHosts=Get-VMHost
foreach ($HyperVHost in $HyperVHosts) {
    Invoke-Command -ComputerName $HyperVHost -ScriptBlock {Get-VM | Get-VMSnapshot | where {$_.SnapshotType -eq "Recovery"} | Remove-VMSnapshot -verbose} 
}

Este se encargara de obtener el listado de los hosts de HyperV administrados por SCVMM, conectarse a cada uno, listar los Checkpoints del tipo “Recovery” (los Checkpoints Standard que hayan sido generados, no serán afectados), y eliminarlos. Importante recalcar que hay que ejecutarlo en un servidor que tenga la consola de SCVMM instalada y contar con los privilegios necesarios.

Espero les sea de utilidad.

Trabajando con HyperV y vSwitches

Se nos ha presentado la necesidad de configurar múltiples Host de Hyper-V en nuestro ambiente laboral, para el cual el tiempo (como siempre) es limitado. Una de las partes que toma un tiempo en configurar son los “Teaming” de Windows así como los switches virtuales.

Con Hyper-V se puede tomar la ventaja de utilizar alguno de los vSwitches para poder Administrar el Hypervisor al crear una vNIC (algo asi como los vkernel ports de VMWare).
En el ejemplo especifico que se muestra a continuación estamos realizando 3 Teaming (de 2 NICs cada una) y a traves de estos separando el trafico de Administracion (Admin), de trafico para las VMs (BackNet) y del “expuesto” a Internet, para nuestro caso varia un poco, pero esta es la base que se utiliza. Toda la información utilizada para este script proviene de un archivo separado por comas (CSV) el cual contiene la información del servidor, Interfase, MacAddress y Grupo al que pertenecera (Admin, BackNet o FrontNet). Obviamente esta información debe ser obtenida de antemano.

El siguiente código esta pensado para ser utilizado como modulo de PowerShell, así que es necesario importarlo.

function Rename-NICs{
    [CmdletBinding()]
    param(
        
        [parameter(Mandatory=$true)]
        [string]$PathCSV
    )

    #Se importa la información desde el CSV
    $CSV=Import-Csv $PathCSV | Select Server,Interface,MacAddress,Grupo
    #Se inicializa una variable que servira para evitar duplicados en los nombres de las interfaces
    $CounterBack=1
    $CounterAdmin=1
    $CounterFront=1

    foreach($item in $CSV) {
        if (get-NetAdapter | where {$_.MacAddress -eq $item.MacAddress}) {
            switch($item.Grupo) {
                #Si la MAC address en el archivo esta etiquetada para ser parte del vSwitch de Administración, se etiqueta con esta función.
                'Admin' {
                    get-NetAdapter | where {$_.MacAddress -eq $item.MacAddress} | Rename-NetAdapter -NewName "phyAdministracion$CounterAdmin"
                    $CounterAdmin=$CounterAdmin+1
                }
                #Si la MAC address en el archivo esta etiquetada para ser parte del vSwitch de BackNet (VMs), se etiqueta con esta función.
                'BackNet' {
                    get-NetAdapter | where {$_.MacAddress -eq $item.MacAddress} | Rename-NetAdapter -NewName "phyBackNet$CounterBack"
                    $counterBack=$CounterBack+1
                }
                #Si la MAC address en el archivo esta etiquetada para ser parte del vSwitch de FrontNet (VMs), se etiqueta con esta función.
                'FrontNet' {
                    get-NetAdapter | where {$_.MacAddress -eq $item.MacAddress} | Rename-NetAdapter -NewName "phyFrontNet$CounterFront"
                    $counterFront=$CounterFront+1
                }
            }
        }
    }
} 

<#La siguiente función se encarga de crear los NIC Teaming y ademas genera los vSwitches.
La parte de la asignación de las direcciones IP puede realizarse a traves de una variable, pero sigo trabajando en eso.
#>
Function Crea-NicTeams {
    [CmdletBinding()]

    $AdministracionNICS = Get-NetAdapter | where {$_.Name -like 'phyAdministracion*'} | %{$_.Name}
    $BackNetNICS = Get-NetAdapter | where {$_.Name -like 'phyBackNet*'} | %{$_.Name}
    $FrontNetNICS = Get-NetAdapter | where {$_.Name -like 'phyFrontNet*'} | %{$_.Name}

    New-NetLbfoTeam -Name TeamAdministracion -TeamMembers $AdministracionNICS -TeamingMode SwitchIndependent -LoadBalancingAlgorithm Dynamic -Confirm:$False
    New-VMSwitch -Name AdminSwitch -NetAdapterName TeamAdministracion –MinimumBandwidthMode Weight –AllowManagementOS $false

    New-NetLbfoTeam -Name TeamBackNet -TeamMembers $BackNetNICS -TeamingMode SwitchIndependent -LoadBalancingAlgorithm Dynamic -Confirm:$False
    New-VMSwitch -Name BackNetSwitch -NetAdapterName TeamBackNet –MinimumBandwidthMode Weight –AllowManagementOS $false

    New-NetLbfoTeam -Name TeamFrontNet -TeamMembers $FrontNetNICS -TeamingMode SwitchIndependent -LoadBalancingAlgorithm Dynamic -Confirm:$False
    New-VMSwitch -Name FrontNetSwitch -NetAdapterName TeamFrontNet –MinimumBandwidthMode Weight –AllowManagementOS $false


    #Crea las vNICs para Administración del Host de Hyper-V
    Add-VMNetworkAdapter -ManagementOS -Name vAdminNet -switchName AdminSwitch
    Rename-NetAdapter -Name "vEthernet (vAdminNet)" -NewName vAdminNet
    Set-VMNetworkAdapterVlan -ManagementOS -VMNetworkAdapterName vAdminNet -Access -VLanID 457
    New-NetIpAddress -InterfaceAlias vAdminNet -IPAddress 172.20.67.41 -PrefixLength 25 -DefaultGateway 172.23.67.127

    #Crea las vNIC dentre de la vLAN alcanzable para las VMs del Host de Hyper-V
    Add-VMNetworkAdapter -ManagementOS -Name vBackNet -switchName AdminSwitch
    Rename-NetAdapter -Name "vEthernet (vBackNet)" -NewName vBackNet
    Set-VMNetworkAdapterVlan -ManagementOS -VMNetworkAdapterName vBackNet -Access -VLanID 417
    New-NetIpAddress -InterfaceAlias vBackNet -IPAddress 172.20.47.41 -PrefixLength 25 -DefaultGateway 172.23.46.127

}