vSphere PowerCLI

Get-View Parte III: Rendimiento

Como vimos en la entrada anterior, con Get-View podemos obtener miles de objetos en apenas segundos. En este articulo voy a realizar unas pruebas de rendimiento de este cmdlet de vSphere PowerCLI para ver como se comporta en diferentes ejemplos.

Esta entrada forma parte de la serie de artículos sobre Get-VM y Get-View:

  1. GET-VM PARTE I: LO BASICO
  2. GET-VM PARTE II: RENDIMIENTO
  3. GET-VIEW PARTE I: LO NO TAN BASICO
  4. GET-VIEW PARTE II: CASO PRÁCTICO
  5. GET-VIEW PARTE III: RENDIMIENTO
  6. GET-VM VS GET-VIEW: CONCLUSIONES

Para los test de rendimiento voy a utilizar Measure-Command, al igual que el segundo artículo de esta serie, Get-VM Parte II: Rendimiento, y con las mismas condiciones.

Vamos a ello!

1. Formas de obtener objetos

En este primer apartado, voy a usar diferentes formas de entrada a través de sus parámetros.

Recordaros que por defecto, y a diferencia de Get-VM que solo retorna unas pocas propiedades,  Get-View retorna todas. Esto significa que tendremos cientos de datos listos para ser consultados.

1.1 Obtener una maquina por Id

Empezamos obteniendo una maquina directamente por su Id con todas sus propiedades:

$vm = get-view -Id VirtualMachine-vm-650452
Get-View Test 1.1 Obtener una maquina por Id
Get-View Test 1.1 Obtener una maquina por Id

Resultado: 18ms para una maquina directamente por el Id.

1.2 Obtener por Id otros tipos de vistas

Algunas vistas tardan más y otras menos. En estos ejemplos voy a retornar un datastore, una carpeta y un cluster:

$datastore = get-view -Id Datastore-datastore-2881
$folder    = get-view -Id Folder-group-v3361
$cluster   = get-view -Id ClusterComputeResource-domain-c517428
Get-View Test 1.2 Otros tipos de vistas por Id

Resultados: entre 13 y 50 ms, dependiendo del tipo.

1.3 Obtener una maquina por VIObject

En este caso usamos el parámetro VIObject. El resultado será el mismo que con Id dado que usara la clave del objeto para ejecutar la consulta.

$vm = get-vm Bi-Lab001
$vmview = get-view -VIObject $vm
Get-View Test 1.3: Obtener una maquina por VIObject
Get-View Test 1.3: Obtener una maquina por VIObject

Resultado: 24ms para una maquina por VIObject

1.4 Obtener una maquina por Id + Get-VIObjectByVIView

Ahora convertimos el objeto vista devuelto en VIObject:

$vm = get-view -Id VirtualMachine-vm-650452 | Get-VIObjectByVIView
Get-View Test 1.4: Obtener una maquina por Id + Get-VIObjectByVIView
Get-View Test 1.4: Obtener una maquina por Id + Get-VIObjectByVIView

Resultado: 100 ms para una maquina directamente por el Id y obtener su ViObject.

Get-VM tarda un mínimo de 2 segundos en cualquier condición. Los 100 ms que ha tardado Get-View son 20 veces menos para obtener exactamente lo mismo!!

1.5 Obtener todas las maquinas

Y por último vamos a obtener TODAS las máquinas de vCenter con todos sus datos. Este es sin duda el «peor» escenario posible en cuanto a rendimiento se refiere, teniendo en cuenta que raro será que necesitemos todos sus propiedades.

$vms = get-view -ViewType VirtualMachine 
Get-View Test 1.5: Obtener todas las maquinas
Get-View Test 1.5: Obtener todas las maquinas

Resultado: 56 segundos para 5892 máquinas con todas sus propiedades.


Tabla Resumen con los resultados de las pruebas con diferentes parámetros de entrada:

PruebaResultado
1.1 Una maquina por Id18ms
1.2 Otras vistas por Id13-50 ms
1.3 Una maquina por VIObject24 ms
1.4 Una maquina por Id + Get-VIObjectByVIView18ms + 100ms
1.5 Todas las maquinas56 segundos

2. Seleccionando Propiedades

En el ultimo test ha tardado casi un minuto, que esta muy bien para la cantidad de datos que nos da, pero que en su mayor parte no necesitamos. Por eso voy a realizar alguna prueba seleccionando solo algunas propiedades y ver como se comporta.

En el caso de querer solo el nombre, como vimos en el articulo de Get-View Parte II: Caso Practico para generar los hashtables, ya vimos los tiempos que tardaba para clusters, hosts y folders.

2.1 Obtener solo el nombre de todas las maquinas

$vms = get-view -ViewType VirtualMachine -Property Name
$vms.count
Get-View Test 2.1: 2.1 Obteniendo solo el nombre de todas las maquinas
Get-View Test 2.1: 2.1 Obteniendo solo el nombre de todas las maquinas

Resultado: 2 segundos para 5892 máquinas con solo su nombre.

2.2 Obtener 3 propiedades de todas las maquinas

Ahora añado tres propiedades explícitamente del mismo subobjeto Summary.Runtime: ConectionState, PowerState y BootTime.

Si especifico lo del sub-objeto es porque afecta al rendimiento, como vimos en Get-VM.

$vms = get-view -ViewType VirtualMachine -Property Name, Summary.Runtime.ConnectionState, summary.Runtime.PowerState, Summary.Runtime.BootTime
Get-View Test 2.2 Obtener 3 propiedades del mismo sub-objeto de todas las maquinas
Get-View Test 2.2 Obtener 3 propiedades del mismo sub-objeto de todas las maquinas

Resultado: 2 segundos, un poco mas que solo el nombre.

2.3 Obtener sub-objeto de todas las maquinas

Ahora añado el subobjeto Summary.Runtime completo, sin especificar ninguna propiedad.

$vms = get-view -ViewType VirtualMachine -Property Name, Summary.Runtime
Get-View Test 2.3 Obtener sub-objeto de todas las maquinas
Get-View Test 2.3 Obtener sub-objeto de todas las maquinas

Resultado: 6 segundos. Se ha triplicado el tiempo.

Obtener el subobjeto completo es mucho mas cómodo que especificar propiedad a propiedad, pero también bastante mas lento.

Get-View Sub-objeto Summary.Runtime completo
Get-View Sub-objeto Summary.Runtime completo

Por eso es muy recomendable dedicar un rato a seleccionar aquellos datos que necesitamos, como en el Test 2.1 o como voy a probar en el siguiente.

2.4 Obtener muchas propiedades de todas las maquinas

Ahora vamos a obtener solo ciertas propiedades que nos interesan, que son las mismas que en Get-VM Parte II: Rendimiento.

$propiedades = @(
    "Name",
    "Runtime.Host"
    "Parent", 
    "Runtime.PowerState", 
    "Guest.ToolsStatus", 
    "Guest.ToolsVersion",
    "Guest.Net",
    "CustomValue",
    "Config.Annotation", 
    "Summary.Config.InstanceUuid",
    "Config.Version",
    "Guest.Hostname",
    "Summary.Config.GuestFullName",
    "Config.Hardware.NumCPU", 
    "Config.Hardware.MemoryMB", 
    "Summary.Storage.Committed", 
    "Config.CreateDate"
)
$vms = get-view -ViewType VirtualMachine -Property $propiedades|
    select name,
    @{n="vCenter";e={$_.client.ServiceUrl.Split("/")[2]}},
    @{n="Host";e={$_.Runtime.Host}},
    @{n="Folder";e={$_.Parent}},
    @{n="Tools Status";e={$_.Guest.ToolsStatus}},
    @{n="Tools Version";e={$_.Guest.ToolsVersion}},
    @{n="IPAddress";e={$_.Guest.Net.IpAddress}},
    @{n="CustomFields";e={$_.CustomValue}},
    @{n="Notas";e={$_.Config.Annotation}},
    @{n="UUID";e={$_.Summary.Config.InstanceUuid}},
    @{n="MoRef";e={$_.MoRef}},
    @{n="HardwareVersion";e={$_.Config.Version}},
    @{n="DNSName";e={$_.Guest.Hostname}},
    @{n="SO";e={$_.Summary.Config.GuestFullName}},
    @{n="CPU"; e={$_.Config.Hardware.NumCPU}},
    @{n="RAM"; e={$_.Config.Hardware.MemoryMB}},
    @{n="Espacio"; e={$_.Summary.Storage.Committed}},
    @{n="CreateDate";e={$_.Config.CreateDate}}
Get-View Test 2.4: Obtener muchas propiedades de todas las maquinas
Get-View Test 2.4: Obtener muchas propiedades de todas las maquinas

Resultado: 9 segundos para todas las máquinas y con muchas propiedades

El resultado de la prueba es algo superior al del articulo anterior del caso practico (7 segundos), porque obtengo mas propiedades.

Además en esta prueba selecciono un sub-objeto completo: Guest.Net, que es la única forma de retornar las IPs, por la limitación comentada en la primera entrada de Get-View: La propiedad debe existir en TODOS los objetos consultados. Y no todas las maquinas tienen IP.


Tabla Resumen con los resultados de las pruebas seleccionando diferentes propiedades de todas las maquinas:

Prueba sobre todas las maquinasResultado
2.1 Solo el nombre2 segundos
2.2 Tres propiedades mismo subobjeto2 segundos
2.3 Sub-objeto completo6 segundos
2.4 Muchas propiedades de todo tipo9 segundos

3. Filtrado

En esta sección voy a probar con unos ejemplos de filtrado con el parámetro –Filter, que nos permite pedir a vCenter solo aquellos objetos que cumplen la condición. Muchísimo mejor que traer todos y filtrar despues con Where.

3.1 Filtrado de una maquina por nombre

Empiezo por filtrar una maquina por su nombre:

$vm = get-view -ViewType VirtualMachine -Filter @{name = "Bi-Lab001"}
Get-View Test 3.1: Filtrado de una maquina por nombre
Get-View Test 3.1: Filtrado de una maquina por nombre

Resultado: 300ms para una maquina filtrada por nombre

3.2 Filtrado de máquinas encendidas

Se va a filtrar la propiedad PowerState para que retorne solo las maquinas encendidas.

$vms = get-view -ViewType VirtualMachine -Property Name -Filter @{"Runtime.PowerState" = "PoweredOn"}
Get-View Test 3.2: Filtrado de máquinas encendidas

Resultado: 1500 ms

3.3 Filtrado de máquinas con las Tools Running

Ahora se va a filtrar la propiedad ToolsRuningStatus para que retorne solo las maquinas con las tools Running.

$vms = get-view -ViewType VirtualMachine -Property Name -Filter @{"Guest.ToolsRunningStatus" = "toolsRunning"}
Get-View Test 3.3 Filtrado de máquinas con las Tools Running
Get-View Test 3.3 Filtrado de máquinas con las Tools Running

Resultado: 1800 ms

3.4 Filtrado de máquinas por contenido de Notas

En este ejemplo, filtro la propiedad Annotation para obtener solo las maquinas que contengan «Windows» en sus notas.

$vms = get-view -ViewType VirtualMachine -Property Name -Filter @{"Config.Annotation" = "windows"}
Get-View Test 3.4 Filtrado de máquinas por contenido de Notas
Get-View Test 3.4 Filtrado de máquinas por contenido de Notas

Resultado: 2 segundos

3.5 Filtrado de máquinas por varias condiciones

Y ahora con las 3 condiciones anteriores juntas, que recordemos se unen usando operador AND.

$filter = @{
    "Runtime.PowerState" = "PoweredOn"
    "Guest.ToolsRunningStatus" = "toolsRunning"
    "Config.Annotation" = "windows"
}
$vms = get-view -ViewType VirtualMachine -Property Name -Filter $filter } 
$vms.count
Get-View Test 3.5 Filtrado de máquinas por varias condiciones
Get-View Test 3.5 Filtrado de máquinas por varias condiciones

Resultado: 3,5 segundos

Casi el doble de tiempo, aunque sigue siendo razonable para la potencia que nos ofrece.

3.6 Filtrado por fichero texto

¿Y cómo filtro un listado de máquinas de un fichero CSV o TXT?

Dado que no podemos pasar un conjunto de nombres directamente, tenemos varias alternativas:

3.6.1 Where

Como Get-View es tan rápido, podríamos traernos TODAS las máquinas y filtrar después con un WHERE sin apenas penalización.

$maquinas = get-content 500vms.csv
$vms = get-view -ViewType VirtualMachine -Property Name
$vmFiltradas = $vms |where {$maquinas -contains $_.Name}
Get-View Test 3.6.1 Filtrado por fichero texto con where

Resultados: 2 segundos para 489 máquinas

info El operador Contains de Powershell nos permite filtrar los objetos de un array, como Like o Match, pero sobre el contenido exacto del elemento. Devuelve los elementos del array A que contengan el valor X. Es especialmente eficaz para obtener los elementos de un array que existen en otro, que de otra forma deberíamos realizar con un foreach.

info Para saber mas sobre como comparar arrays, os recomiendo este articulo de Adam Bertram: https://adamtheautomator.com/compare-powershell-arrays/

En el ejemplo:

  • $_.Name: es un array con el nombre de todas las maquinas (5892) pasado por pipe de $vms.
  • $maquinas: es un array con el nombre de maquinas obtenidos del fichero de texto (489)
  • $maquinas -contains $_.Name: retorna del array $maquinas aquellas que existen en el array $_.Name
  • $vmFiltradas: Contiene por tanto solo los objetos vistas de las maquinas del fichero de texto.
3.6.2 Expresion Regular

Otra opción es jugar con las expresiones regulares y el operador OR, que se representa con «|»

La idea es cargar todos los nombres de maquinas del fichero de texto: Trae las maquinas que su nombre sea Maquina1, …, o sea MaquinaN.

Para ello genero un variable string que por cada maquina le añade un «|» al final. Cuando termine con todas, borra el ultimo «I» (ultima posición del string), quedando algo asi: Maquina1|…|MaquinaN

$regex = Get-Content 500vms.csv | ForEach-Object -Begin {$rex = ""} -Process {$rex += "^$($_)`$|"} -End {$rex.Substring( 0, ($rex.Length - 1))}

¿Y esto funciona? Visto así no parece demasiado optimo…

Ahora ejecuto el Get-View

$vms = get-view -ViewType VirtualMachine -Property Name -Filter @{name = $regex}
Get-View Test 3.6.2 Filtrado por fichero texto con Exprexion Regular y operador OR
Get-View Test 3.6.2 Filtrado por fichero texto con Exprexion Regular y operador OR

Resultados: 660 ms para 489 máquinas.

Ha pesar de lo poco ortodoxo que parece, resulta ser 3 veces mas rápido que con el metodo Where.


Tabla Resumen con los resultados de las pruebas con los filtros:

PruebaResultado
3.1 Filtrado de una maquina por nombre0,3 segundos
3.2 Filtrado de máquinas encendidas1,5 segundos
3.2 Filtrado de maquinas con las tools running1,8 segundos
3.2 Filtrado de maquinas por campo notas2 segundos
3.5 Filtrado de máquinas por varias condiciones3,5 segundos
3.6.1 Filtrado por fichero texto con Where2,1 segundos
3.6.2 Filtrado por fichero texto con RegEx0,66 segundos

4. Conclusiones

Podría seguir haciendo más pruebas, pero creo que ha quedado demostrado la velocidad con la que trabaja los datos Get-View en todos los casos.

Ventajas

  • Rapidez: Es muy rápido en todos los casos, pero especialmente cuando queremos trabajar con grandes cantidades de objetos.
  • Potencia: Poder utilizar expresiones regulares como filtrado

Inconvenientes

  • Complejidad: Es bastante más complejo de trabajar por muchos motivos:
    • Por el uso de claves en vez de nombres, que requieren ciertas técnicas, como los diccionarios (hashtables), para no perder su eficacia.
    • Por el uso en los filtros de hashtables y expresiones regulares.

Su rapidez y potencia hace de Get-View un gran aliado para scripts que obtienen gran cantidad de datos, pero no será nunca la primera opción para obtener 4 datos desde la propia consola de Powershell.


En el próximo y último artículo de la serie, repasare todo lo visto hasta ahora con las conclusiones de ambos cmdlets.

Cualquier duda o pregunta, responderé encantando en los comentarios.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *