In order to check the patch compliance i run a simple command sequence:
get-vmhost | Scan-Inventory -Verbose -UpdateType HostPatch
$Baseline = Get-Baseline -Name 'Non-Critical Host Patches (Predefined)', 'Critical Host Patches (Predefined)', 'Host Security Patches (Predefined)'
get-compliance -Entity hostname -baseline $Baseline
I get this :
Entity Status Baseline
------ ------ --------
hostname NotCompliant VMware.VumAutomation.Types.PatchBaselineImpl
hostname Compliant VMware.VumAutomation.Types.PatchBaselineImpl
Why is the Baseline name changed?
I get the same result if I do not declare entity or baseline :
get-vmhost | Scan-Inventory -Verbose -UpdateType HostPatch
get-vmhost | Get-Compliance -Detailed
system:
Name Value
---- -----
PSVersion 5.1.19041.1682
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.19041.1682
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
Name Version
---- -------
VMware.Vim 7.0.3.19601056
VMware.VimAutomation.Cis.Core 12.6.0.19601368
VMware.VimAutomation.Common 12.7.0.20067789
VMware.VimAutomation.Core 12.7.0.20091293
VMware.VimAutomation.Sdk 12.7.0.20067606
VMware.VimAutomation.Vds 12.7.0.20091295
VMware.VumAutomation 12.7.0.20091294
The Get-Compliance cmdlet can use OBN on the Entity parameter.
In fact I took that 'hostname' from your original code.
You will have to replace with the name of an actual ESxi node in your VCSA.
There was an issue with the NumberOfPatches.
This code should fix that
Get-Compliance -Entity <ESXi-name> -Baseline $aseline |
Select-Object @{N='VMHost';E={$_.Entity.Name}},
Status,
@{N='Baseline';E={$_.Baseline.Name}},
@{N='NumberofPatches';E={$_.Baseline.CurrentPatches.Count}}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
The Baseline property is itself an object.
Did you try looking inside that object with
get-compliance -Entity hostname -baseline $Baseline |
Select-Object -ExpandProperty Baseline
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi Luc,
this output is much better. The correct name is displayed:
Name Description Id Type TargetType LastUpdateTime NumberOfPatches
---- ----------- -- ---- ---------- -------------- ---------------
Host Security Patches (Predefined) A predefined baseline for all security patches for hosts 1 Patch Host 07.10.2022 14:13:21 138
Critical Host Patches (Predefined) A predefined baseline for all critical patches for Hosts 2 Patch Host 07.10.2022 14:13:21 196
but now the compliance state is missing. I run my command on another system with little bit older ESXi versions and get this output
get-vmhost | Get-Compliance -Detailed | ft -autosize
Entity Baseline Status CompliantPatches NotCompliantPatches
------ -------- ------ ---------------- ------------------
esxi-05.mpa.lab Host Security Patches Compliant 5 0
esxi-05.mpa.lab Critical Host Patches NotCompliant 51 3
esxi-05.mpa.lab Non-Critical Host Pa. NotCompliant 20 32
That is the info i intend to get.
You can use calculated properties to select the properties from different levels.
For example
get-compliance -Entity hostname -baseline $Baseline |
Select-Object Name,Status,
@{N='Baseline';E={$_.Baseline.Name}},
@{N='NumberofPatches';E={$_.Baseline.NumberOfPatches}}
You can add as many calculated properties as you like.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
It seems that there is a problem :
Yes, there was a quote after $_.Baseline.Name which shouldn't be there.
I corrected the code above
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
There is another problem (AFAIK get-baseline targets entities not hostnames)
get-compliance : 07.10.2022 19:02:43 Get-Compliance Could not find InventoryItem with name 'hostname'.
At C:\code\patch-compl-new.ps1:1 char:1
+ get-compliance -Entity hostname -baseline $Baseline |
The Get-Compliance cmdlet can use OBN on the Entity parameter.
In fact I took that 'hostname' from your original code.
You will have to replace with the name of an actual ESxi node in your VCSA.
There was an issue with the NumberOfPatches.
This code should fix that
Get-Compliance -Entity <ESXi-name> -Baseline $aseline |
Select-Object @{N='VMHost';E={$_.Entity.Name}},
Status,
@{N='Baseline';E={$_.Baseline.Name}},
@{N='NumberofPatches';E={$_.Baseline.CurrentPatches.Count}}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks, yes in general this works,
where can I find the other properties like number of missing patches?
I tried the next step to run the script on a cluster and changed the entity to $cluster but got partially error:
$cluster = Get-Cluster -Name vsan-cluster
PS D:\VMware-HC\code> .\patch-compl-new.ps1
Get-Compliance : 07.10.2022 19:57:13 Get-Compliance fault.SecurityError.summary
In D:\VMware-HC\code\patch-compl-new.ps1:1 Zeichen:1
+ Get-Compliance -Entity vsan-cluster -Baseline $Baseline |
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-Compliance], VimException
+ FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VumAutomation.Commands.GetCompliance
Get-Compliance : 07.10.2022 19:57:13 Get-Compliance fault.SecurityError.summary
In D:\VMware-HC\code\patch-compl-new.ps1:1 Zeichen:1
+ Get-Compliance -Entity vsan-cluster -Baseline $Baseline |
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-Compliance], VimException
+ FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VumAutomation.Commands.GetCompliance
Get-Compliance : 07.10.2022 19:57:13 Get-Compliance fault.SecurityError.summary
In D:\VMware-HC\code\patch-compl-new.ps1:1 Zeichen:1
+ Get-Compliance -Entity vsan-cluster -Baseline $Baseline |
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-Compliance], VimException
+ FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VumAutomation.Commands.GetCompliance
VMHost Status Baseline NumberofPatches
------ ------ -------- ---------------
host06.sp.local Compliant Host Security Patches (Predefined) 138
host06.sp.local NotCompliant Critical Host Patches (Predefined) 196
host03.sp.local Compliant Host Security Patches (Predefined) 138
host03.sp.local NotCompliant Critical Host Patches (Predefined) 196
host04.sp.local Compliant Host Security Patches (Predefined) 138
host04.sp.local NotCompliant Critical Host Patches (Predefined) 196
host05.sp.local Compliant Host Security Patches (Predefined) 138
host05.sp.local NotCompliant Critical Host Patches (Predefined) 196
host02.sp.local Compliant Host Security Patches (Predefined) 138
host02.sp.local NotCompliant Critical Host Patches (Predefined) 196
host01.sp.local Compliant Host Security Patches (Predefined) 138
host01.sp.local NotCompliant Critical Host Patches (Predefined) 196
I get the same errors when I pass a cluster on the Entity parameter.
That seems to be a bug since the documentation states
Specifies a Template, VirtualMachine, VMHost, Cluster, Datacenter, Folder, or VApp object for which you want to retrieve the compliance status.
The results for the ESXi nodes on the cluster are produced though.
I suggest opening an SR.
Since the Update Manager API is, afaik, not public there is no way of finding out what actually fails and causes the error messages
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Yes, i think an SR is the next option.
Where did you find the properties like .Baseline.CurrentPatches.Count ?
That one is a bit more complex to find.
When you look at which properties hide under Baseline with Get-Member
$compliance = Get-Compliance -Entity <ESXi-name> -baseline $baseline
$compliance.Baseline | Get-Member
you'll notice that there is no NumberOfPatches property.
To find out where such a non-existing property is coming from, one good source is the Types file(s) that come with a module.
In this case, for the VMware.VumAutomation module that is the VMware.VumAutomation.Format.ps1xml file.
These 'Types' files define how and which properties of a specific type of object are displayed.
For each object type there is a TableHeaders part and TableRowEntries part.
The order of the properties is the same in both part.
So look up the name in the TableHeaders part and find the corresponding entry in the TableRowEntries part.
The objects produced by the Get-Complaince cmdlet are of the type VMware.VumAutomation.Types.PatchBaselineCompliance.
And the Baseline is an object of type VMware.VumAutomation.Types.PatchBaselineImpl.
When we search in the .ps1xml file for that type (VMware.VumAutomation.Types.PatchBaselineImpl), we see that TableRowEntries part for the NumberOfPatches property says
<ScriptBlock>$_.CurrentPatches.Length</ScriptBlock>
This means that the value for this property is calculated in a script block.
And Length is the same as Count for an array.
Which brings me to
@{N='NumberofPatches';E={$_.Baseline.CurrentPatches.Count}}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Oh yes, that is really a deep dive. Thanks for your explanation.
I will open an SR and reply the results.
Thanks & Regards
Mike
I got a feedback from engineering ;
This will be fixed in the next 13.1 Release of Powercli.
By the meantime you can use this workaround:
get-vmhost | get-compliance | select Entity, @{N="Baseline"; E={$_.Baseline.Name}}, Status | ft -AutoSize
Great to hear, and also glad they pointed to the solution I gave earlier.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
