![¿Por qué el tamaño de archivo Get-VHD devuelve 0 para las máquinas virtuales alojadas en el servidor 2012R2 dentro del trabajo Powershell Runspace?](https://rvso.com/image/718157/%C2%BFPor%20qu%C3%A9%20el%20tama%C3%B1o%20de%20archivo%20Get-VHD%20devuelve%200%20para%20las%20m%C3%A1quinas%20virtuales%20alojadas%20en%20el%20servidor%202012R2%20dentro%20del%20trabajo%20Powershell%20Runspace%3F.png)
Tengo este script para crear un CSV de máquinas virtuales alojadas en nuestros clústeres Hyper-V. ¡Está funcionando muy bien e incluso lo logré separando cada VM en un trabajo!
Nota al margen: no me importaría recibir consejos sobre cómo hacer mi programación de manera más eficiente. El problema principal es que algunos clústeres son WS 2016 y otros son WS 2012R2, que requieren un módulo Hyper-V PowerShell más antiguo. No estoy seguro de cómo paralelizar diferentes módulos, así que simplemente obtengo la lista de VM para cada nodo Hyper-V, los paralelizamos y luego cambio el módulo si el siguiente nodo lo requiere.
De todos modos, mi problema. Aquí está mi guión.
$numThreads = 4
$ScriptBlock = {
Param (
[string]$Cluster,
[string]$Node,
$VM
)
If ($ADComputer = (Get-ADComputer $VM.Name -Properties OperatingSystem)) {
$OS = $ADComputer.OperatingSystem
}
Else {
$OS = 'Unknown (not on domain)'
}
try {
Return [pscustomobject] @{
Cluster = $Cluster
Node = $Node
Name = $VM.Name
OS = $OS
State = $VM.State
Status = $VM.Status
Uptime = "{0:dd} days {0:hh} hours" -f $VM.Uptime
CPUUsage = $VM.CPUUsage
ProcessorCount = $VM.ProcessorCount
'MemoryDemand (GB)' = [math]::Round( $VM.MemoryDemand / 1GB, 2 )
'MemoryAssigned (GB)' = [math]::Round( $VM.MemoryAssigned / 1GB, 2 )
'VHD Size (GB)' = [math]::Round( ((Get-VHD -ComputerName $Node -VMId $VM.Id).FileSize | Measure-Object -Sum).Sum / 1GB, 2 )
Version = $VM.Version
'VLAN IDs' = ($VM | Select-Object -ExpandProperty NetworkAdapters | Select-Object -ExpandProperty VlanSetting).AccessVlanId -Join ", "
'IP Addresses' = ($VM | Select-Object -ExpandProperty NetworkAdapters).IPAddresses -Join ", "
}
}
catch {
Return [pscustomobject] @{
Cluster = $Cluster
Node = $Node
Name = $VM.Name
State = "Script Fail"
Status = $_.Exception.Message
}
}
}
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, $numThreads)
$RunspacePool.Open()
$Jobs = @()
$VMInfoList = @()
ForEach ($Cluster in 'USHOMECLU0', 'USHOMECLU1') {
If ((Get-ADComputer $Cluster -Property OperatingSystem).OperatingSystem -Match '2016') {
Remove-Module Hyper-V
Import-Module Hyper-V -RequiredVersion 2.0.0.0
}
Else {
Remove-Module Hyper-V
Import-Module Hyper-V -RequiredVersion 1.1
}
ForEach ($Node in Get-ClusterNode -Cluster $Cluster) {
Get-VM -ComputerName $Node | ForEach-Object {
$Job = [powershell]::Create().AddScript($ScriptBlock).AddParameter("Cluster", $Cluster).AddParameter("Node", $Node).AddParameter("VM", $_)
$Job.RunspacePool = $RunspacePool
$Jobs += New-Object PSObject -Property @{
Job = $Job
Result = $Job.BeginInvoke()
}
}
}
}
# EndInvoke returns the objects from the background threads
ForEach ($Job in $Jobs) {
$VMInfoList += $Job.Job.EndInvoke($Job.Result)
}
$VMInfoList | Export-Csv -NoTypeInformation C:\PSReports_vms.csv
El problema que tengo es que los trabajos para máquinas virtuales en nodos de Windows Server 2012R2 siempre devuelven 0 para esto:
'VHD Size' = ((Get-VHD -ComputerName $Node -VMId $VM.Id).FileSize | Measure-Object -Sum).Sum
Sin embargo, para los nodos de Windows Server 2016, todas las máquinas virtuales devuelven el valor apropiado. Lo que también es interesante es que si capturo la expresión exacta que se asigna al tamaño de VHD para esas máquinas virtuales alojadas en Server 2012R2 (reemplace las variables con la cadena directa) y la ejecuto fuera del bloque de script para el trabajo, obtengo el valor exacto.