Michael asked if it was possible to produce a report that showed the NX/XD flag setting for all the guests.
Piece of cake I thought, but it turned out to be a bit more complex than that. If you don’t set the NX/XD flag (expose or hide) explicitly on the guest, the hyper-visor will use a default that is defined per OS you can have on the guest.
In the end I think I came up with a script that seems to handle all the different possibilities I encountered.
The script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
$report = @() Get-View -ViewType VirtualMachine | where {!$_.Config.Template} | %{ $vm = $_ $osDefault = $false $osDefaultAmd = $false if($vm.Config.CpuFeatureMask){ $flagLocation = 11 $mask = $vm.Config.CpuFeatureMask $cpuLvl80000001 = $mask | where {$_.Level -eq 0x80000001 -and !$_.Vendor} if($cpuLvl80000001){ $defaultFlag = $cpuLvl80000001.Edx.ToCharArray()[$flagLocation] if($defaultFlag -eq "-"){ $osDefault = $true } } else{ $osDefault = $true } $cpuLvl80000001Amd = $mask | where {$_.Level -eq 0x80000001 -and $_.Vendor -eq "amd"} if($cpuLvl80000001Amd){ $amdFlag = $cpuLvl80000001Amd.Edx.ToCharArray()[$flagLocation] if($amdFlag -eq "-"){ $osDefaultAmd = $true } } else{ $osDefaultAmd = $true } } else{ $osDefault = $true $osDefaultAmd = $true } if($osDefault -or $osDefaultAmd){ $flagLocation = 13 $envBrowser = Get-View $vm.environmentBrowser $params = @($null,$null) $vmConfigOption = $envBrowser.GetType().GetMethod("QueryConfigOption").Invoke($envBrowser,$params) $mask = ($vmConfigOption.GuestOSDescriptor | where {$_.FullName -eq $vm.Config.GuestFullName}).CpuFeatureMask if($osDefault){ $defaultFlag = ($mask | where {$_.Level -eq 0x80000001 -and !$_.Vendor}).Edx.ToCharArray()[$flagLocation] } if($osDefaultAmd){ $amdFlag = ($mask | where {$_.Level -eq 0x80000001 -and $_.Vendor -eq "amd"}).Edx.ToCharArray()[$flagLocation] } } $row = "" | Select VMname, OSdefault,"NX/XD flag","AMD OSdefault","AMD NX/XD flag" $row.VMname = $vm.Name $row.OSdefault = $osDefault $row."NX/XD flag" = &{if($defaultFlag -eq "0"){"hide"}elseif($defaultFlag -eq "H"){"expose"}} $row."AMD OSdefault" = $osDefaultAmd $row."AMD NX/XD flag" = &{if($amdFlag -eq "0"){"hide"}elseif($defaultFlag -eq "H"){"expose"}} $report += $row } $report | Sort-Object -Property VMname | ft -AutoSize -Force |
Annotations
Line 3: The line excludes templates since these don’t have the notion of an NX/XD flag (yet). Once you deploy a new guest from the template, the OS default mask will be used.
Line 8: If the mask hasn’t been set explicitly on the guest, the CpuFeatureMask property will be $null
Line 9,37: The way the mask is represented in the VirtualMachine object and the way it is returned by the QueryConfigOption method is different, hence the different offsets to the location of the NX/XD bit.
Line 14: If a bit is represented by a “-” character that means that the OS default is used.
Line 40: A standard trick to allow the passing of empty strings as a parameter to an SDK method from within PowerShell.
The report
In the following sample report you can see several possibilities.
To following screenshots of the actual settings on these guests will clarify how to interprete the report.
PC11/PC13/PC15: default configuration
The OSdefault and AMD OSdefault columns tell you that the guest is using the OS specific defaults. In the guest’s settings you will see this.
PC12: customised, different AMD mask
From the OSdefault and AMD OSdefault columns you can see that the settings were configured explicitly.
From the NX/XD flag and AMD NX/XD flag columns you see that different settings were used.
PC14: hide flag
No OS defaults, flags manually set to hidden.
PC16: flag in the regular mask from the OS default, flag in the AMD mask set manually
From the OSdefault column you can see that the OS default was used.
From the AMD OSdefault column you see that this is a manual setting.
And the flag settings for the regular and the AMD mask.
Mark
@LucD
I get the same errors as Nicolas, is there an answer?
Thanks.
Nicholas
I tried your script, however when executing against my environment I get the following. Any ideas?
Name Port User
—- —- —-
10.2.228.175 443 corp\ngerasim
You cannot call a method on a null-valued expression.
At C:\Users\ngerasim\AppData\Local\Temp\8f8261d3-fa24-4343-9e90-a21974e2dd97.ps1:45 char:92
+ $defaultFlag = ($mask | where {$_.Level -eq 0x80000001 -and !$_.Vendor}).Edx.ToCharArray <<<< ()[$flagLocation]
+ CategoryInfo : InvalidOperation: (ToCharArray:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\Users\ngerasim\AppData\Local\Temp\8f8261d3-fa24-4343-9e90-a21974e2dd97.ps1:48 char:97
+ $amdFlag = ($mask | where {$_.Level -eq 0x80000001 -and $_.Vendor -eq "amd"}).Edx.ToCharArray <<<< ()[$flagLocation]
+ CategoryInfo : InvalidOperation: (ToCharArray:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\Users\ngerasim\AppData\Local\Temp\8f8261d3-fa24-4343-9e90-a21974e2dd97.ps1:25 char:49
+ $amdFlag = $cpuLvl80000001Amd.Edx.ToCharArray <<<< ()[$flagLocation]
+ CategoryInfo : InvalidOperation: (ToCharArray:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\Users\ngerasim\AppData\Local\Temp\8f8261d3-fa24-4343-9e90-a21974e2dd97.ps1:25 char:49
+ $amdFlag = $cpuLvl80000001Amd.Edx.ToCharArray <<<< ()[$flagLocation]
+ CategoryInfo : InvalidOperation: (ToCharArray:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\Users\ngerasim\AppData\Local\Temp\8f8261d3-fa24-4343-9e90-a21974e2dd97.ps1:25 char:49
+ $amdFlag = $cpuLvl80000001Amd.Edx.ToCharArray <<<< ()[$flagLocation]
+ CategoryInfo : InvalidOperation: (ToCharArray:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\Users\ngerasim\AppData\Local\Temp\8f8261d3-fa24-4343-9e90-a21974e2dd97.ps1:25 char:49
+ $amdFlag = $cpuLvl80000001Amd.Edx.ToCharArray <<<< ()[$flagLocation]
+ CategoryInfo : InvalidOperation: (ToCharArray:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Operation is not valid due to the current state of the object.
At :line:0 char:0
LucD
@Nicholas Against which ESX(i) server or vCenter version (and build) are you running the script ?
Is the NX/XD flag set on the guest level or do you use the OS default ?
Perhaps you can isolate 1 guest where you experience the error and forward me a screenshot of the