Powershell

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.

¿VMs con MAC Address Duplicadas en Hyper-V?

*Nota importante: Si tus VMHost estan siendo administrados por System Center VMM, este articulo no aplica, ya que el rango de MAC Addresses es administrado por SCVMM.

Es posible que construyendo sus primeros Hosts de Hyper-V encuentren que algunas de sus VMs que viven en hosts diferentes tengan problemas de conectividad, esto debido a que las MAC address de las VMs se duplican y le genera conflictos a la tabla ARP de los switches. ¿Porque sucede esto?

Hyper-V tiene un mecanismo en el cual cada VMHost genera un rango de MAC Address que serán asignados a cada vNIC conectada a los vSwitches declarados dentro del Host. Esta Mac Address se conforma de la siguiente manera:

00-15-5D

– XX –

XX

– 00

Rango predefinido para HyperV Basado en el 3er Octeto de la dirección IP del Host Basado en el 4to Octeto de la direccion IP Rango inicial y Rango final

 

Los últimos 2 dígitos son “00” para el rango inicial y “FF” para el rango final.

Existe un pequeño issue con esta lógica y es que debido a que todos los servidores al momento de ser instalados, el rango de Mac Address asignado es siempre el mismo, siendo en todos los casos 00-15-5D-00-00-00 hasta  00-15-5D-00-00-FF. Si no ajustamos previamente este rango, o bien, si el vSwitch es generado antes de asignarle una dirección IP estática al VMHost, y se generan los vSwitches con el VMHost usando las direcciones IP de APIPA (Automatic Private Internet Protocol Addressing)  y  además tenemos en nuestro ambiente 2 o mas VMhosts, cada uno de estos generará MAC address para las VMs y vNICs empezando desde el rango inferior e ira incrementado en uno.  Aqui un ejemplo:

VMHost 1

VM1      00-15-5D-00-00-00

VM2      00-15-5D-00-00-01

VMHost 2

VM3      00-15-5D-00-00-00

VM4      00-15-5D-00-00-01

En el ejemplo anterior, tendriamos un conflicto con la MAC address entre la VM1 y VM3, y el mismo caso para la VM2 y VM4

¿Como evitar esto?

La recomendación es configurar previamente los rangos de MAC address que serán asignados a las VMs en cada VMHost, esto puede realizarse con Powershell y tansolo es necesario tener armada una tabla de los rangos a usar basados en la tabla mostrada al principio de esta entrada. Asi podrian armar una tabla similar a la siguiente:

Servername MinMACAddress MaxMACAddress
VMHost1 00-15-5D-46-0B-00 00-15-5D-46-0B-FF
VMHost2 00-15-5D-46-0C-00 00-15-5D-46-0C-FF
VMHost3 00-15-5D-46-0D-00 00-15-5D-46-0D-FF

En el ejemplo mostrado en la tabla, los primeros 3 bloques, es el rango pre-definido por HyperV (“00-15-5D”). Para el 4to bloque (“46”)corresponderia al 3er Octeto de las direcciones IP de nuestros VMHosts, como en nuestro caso el segmento es “172.18.70.0/24”, vemos que el 3er octeto siempre será “70”, lo cual en hexadecimal es….. “46” 🙂  . El cuarto bloque corresponde al 4to octeto de la dirección IP, por ejemplo para el VMHost1 la dirección IP es 172.18.70.11, al tomar el 4to octeto (“11”) y convertirlo a hexadecimal, obtenemos “0B” y como podrán deducir el la IP del VMHost2 es 172.18.70.12. Ya con esta tabla armada, la podemos tener en un CSV y tomar el siguiente bloque para usar en Powershell.

 


$MacAddress = import-csv C:\MacAddresses.csv
#En este loop se establece el Rango de MacAddress para cada VMHost.
foreach($server in $MacAddress ){
    if($env:computername -eq $server.ServerName){
        Set-VMHost -MacAddressMinimum $server.MinMacAddress -MacAddressMaximum $server.MaxMacAddress
    }
}

La lógica de este pedazo de código es simple. Tan solo hay que pegar en un CSV la tabla que preparamos previamente con los rangos de MAC Addresses, este archivo es importado en una variable y se procesa. Si se encuentra que el Hostname del servidor donde esta siendo ejecutado, coincide con el valor de la columna “Servername“, entonces se establece el rango de MacAddresses establecido en las columnas “MinMacAddress” y “MaxMacAddress“. Si desean hacerlo de manera manual, pueden usar el cmdlet Set-VMHost con los parametros MacAddressMinimum y MacAddressMaximum. Con esto, las MAC Address asiganadas a cada VM en cada VMHost, variaran.

 

Moviendo Objetos del Directorio Activo con PowerShell

Que tal

Este es un post corto en donde solo voy a exponer una situación que se me presentó trabajando con usuarios en el Directorio activo y la necesidad de reubicarlos en diferentes OUs de acuerdo a ciertos valores dentro de alguno de sus atributos.

Es cierto que para poder encontrar usuarios tenemos el comando “Get-ADUser” pero al trabajar con el vi que si bien era sencillo encontrar los usuarios, no me era fácil usar el “pipe” para redirigir los objetos salientes hacia el comando “move-ADObject” ya que el objeto recibido no era el esperado precisamente por este CMDlet.

Realizando mayores pruebas y leyendo algo de la documentación, encontré que el cmdlet “Get-ADObject” me podria ser de mayor utilidad (y lo fue) ya que este comando arroja como resultante un objeto del directorio activo(que puede ser cualquiera, dicese Grupos, computers, Users y cualquier objeto que pueda ser almacenado en el Directorio activo) y a traves del parametro “LDAPfilter”, podemos restringir a aquellos objetos que estemos buscando especificamente, ya que en este filtro podemos introducir cualquier filtro LDAP permitido).

En mi ejemplo especifico buscaba que ciertos usuarios que tuvieran un valor especifico dentro del atributo “userprincipalname” fueran movidos de la OU “Test” hacia la OU “Test2”, y aqui el ejemplo.

Get-ADObject -searchBase "OU=Test,OU=BaseOU,DC=prueba,DC=local" -LDAPfilter "(userprincipalName=*Juan*)" | move-adobject -targetpath "OU=Test2,OU=BaseOU,DC=Prueba,DC=local" -verbose

Como pueden ver es una simple linea y los resulotados son enviados hacia el cmdlet “move-ADObject” y los resultados han sido los esperados.

Como pueden ver, la facilidad de proveer un filtro de LDAP, les abre muchas posibilidades para jugar con este comando, ademas de que el tipo de objeto que arroja el cmdlet, les permitirá interactuar con otros cmdlet disponibles en el modulo de Active Directory.

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

}