From 6de511c9fb0e5b9a53966167b024c1747790fb42 Mon Sep 17 00:00:00 2001 From: Lord Hepipud Date: Tue, 20 Jun 2023 17:45:04 +0200 Subject: [PATCH] Adds new plugin data provider handling and cpu data --- doc/100-General/10-Changelog.md | 3 +- .../Test-IcingaForWindowsCmdletLoader.psm1 | 22 +++++ .../cpu/Get-IcingaProviderDataValuesCpu.psm1 | 89 +++++++++++++++++++ lib/provider/core/Get-IcingaProviderData.psm1 | 39 ++++++++ .../core/Get-IcingaProviderElement.psm1 | 18 ++++ .../core/New-IcingaProviderObject.psm1 | 17 ++++ 6 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 lib/core/tools/Test-IcingaForWindowsCmdletLoader.psm1 create mode 100644 lib/provider/assets/cpu/Get-IcingaProviderDataValuesCpu.psm1 create mode 100644 lib/provider/core/Get-IcingaProviderData.psm1 create mode 100644 lib/provider/core/Get-IcingaProviderElement.psm1 create mode 100644 lib/provider/core/New-IcingaProviderObject.psm1 diff --git a/doc/100-General/10-Changelog.md b/doc/100-General/10-Changelog.md index 85f834c8..b7c9e446 100644 --- a/doc/100-General/10-Changelog.md +++ b/doc/100-General/10-Changelog.md @@ -7,7 +7,7 @@ documentation before upgrading to a new release. Released closed milestones can be found on [GitHub](https://github.com/Icinga/icinga-powershell-framework/milestones?state=closed). -## 1.11.0 (2023-05-16) +## 1.11.0 (2023-08-01) [Issues and PRs](https://github.com/Icinga/icinga-powershell-framework/milestone/26) @@ -29,6 +29,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic * [#623](https://github.com/Icinga/icinga-powershell-framework/issues/623) Adds support to provide the Icinga service user written as `user@domain` * [#633](https://github.com/Icinga/icinga-powershell-framework/pull/633) Adds support for Icinga 2.14.0 native Icinga for Windows API communication * [#635](https://github.com/Icinga/icinga-powershell-framework/pull/635) Adds support for `Write-IcingaAgentApiConfig` function to configure the Icinga Agent TLS cipher list setting by new argument `-CipherList` +* [#637](https://github.com/Icinga/icinga-powershell-framework/pull/637) Adds new base handling for future data providers with first metrics for `CPU` information * [#640](https://github.com/Icinga/icinga-powershell-framework/issues/640) Adds support to set the flag `-NoSSLValidation` for Cmdlets `icinga` and `Install-Icinga`, to ignore errors on self-signed certificates within the environment * [#643](https://github.com/Icinga/icinga-powershell-framework/pull/643) Adds support for `-RebuildCache` flag on `icinga` cmd to rebuild component cache as well * [#644](https://github.com/Icinga/icinga-powershell-framework/pull/644) Adds progress bar output to repository interaction (sync, update, new) instead of plain text output diff --git a/lib/core/tools/Test-IcingaForWindowsCmdletLoader.psm1 b/lib/core/tools/Test-IcingaForWindowsCmdletLoader.psm1 new file mode 100644 index 00000000..58ba1b5f --- /dev/null +++ b/lib/core/tools/Test-IcingaForWindowsCmdletLoader.psm1 @@ -0,0 +1,22 @@ +function Test-IcingaForWindowsCmdletLoader() +{ + param ( + [string]$Path = '' + ); + + if ([string]::IsNullOrEmpty($Path)) { + return $FALSE; + } + + if ((Test-Path -Path $Path) -eq $FALSE) { + return $FALSE; + } + + $FrameworkRootDir = [string]::Format('{0}*', (Get-IcingaForWindowsRootPath)); + + if ($Path -NotLike $FrameworkRootDir) { + return $FALSE; + } + + return $TRUE; +} diff --git a/lib/provider/assets/cpu/Get-IcingaProviderDataValuesCpu.psm1 b/lib/provider/assets/cpu/Get-IcingaProviderDataValuesCpu.psm1 new file mode 100644 index 00000000..e61ebdac --- /dev/null +++ b/lib/provider/assets/cpu/Get-IcingaProviderDataValuesCpu.psm1 @@ -0,0 +1,89 @@ +function Get-IcingaProviderDataValuesCpu() +{ + param ( + [switch]$IncludeDetails = $FALSE + ); + + $CpuData = New-IcingaProviderObject -Name 'Cpu'; + $CpuCounter = New-IcingaPerformanceCounterArray '\Processor Information(*)\% Processor Utility'; + $CounterStructure = New-IcingaPerformanceCounterStructure -CounterCategory 'Processor Information' -PerformanceCounterHash $CpuCounter; + [int]$TotalCpuThreads = 0; + [decimal]$TotalCpuLoad = 0; + [hashtable]$SocketList = @{ }; + + foreach ($core in $CounterStructure.Keys) { + [string]$Socket = $core.Split(',')[0]; + [string]$CoreId = $core.Split(',')[1]; + [string]$SocketName = [string]::Format('Socket #{0}', $Socket); + + if ($Socket -eq '_Total' -Or $CoreId -eq '_Total') { + continue; + } + + if ($SocketList.ContainsKey($SocketName) -eq $FALSE) { + $SocketList.Add( + $SocketName, + @{ + 'ThreadCount' = 0; + 'TotalLoad' = 0; + } + ); + } + + if ((Test-PSCustomObjectMember -PSObject $CpuData.Metrics -Name $SocketName) -eq $FALSE) { + $CpuData.Metrics | Add-Member -MemberType NoteProperty -Name $SocketName -Value (New-Object PSCustomObject); + } + + [decimal]$CoreLoad = $CounterStructure[$core]['% Processor Utility'].value; + + $CpuData.Metrics.$SocketName | Add-Member -MemberType NoteProperty -Name $CoreId -Value $CoreLoad; + $CpuData.MetricsOverTime.MetricContainer | Add-Member -MemberType NoteProperty -Name $SocketName -Value $null -Force; + + $SocketList[$SocketName].ThreadCount += 1; + $SocketList[$SocketName].TotalLoad += $CoreLoad; + } + + $CpuData.Metadata | Add-Member -MemberType NoteProperty -Name 'Sockets' -Value (New-Object PSCustomObject); + + foreach ($entry in $SocketList.Keys) { + $SocketList[$entry].TotalLoad = $SocketList[$entry].TotalLoad / $SocketList[$entry].ThreadCount; + $TotalCpuLoad += $SocketList[$entry].TotalLoad; + $TotalCpuThreads += $SocketList[$entry].ThreadCount; + + $CpuData.Metadata.Sockets | Add-Member -MemberType NoteProperty -Name $entry -Value (New-Object PSCustomObject); + $CpuData.Metadata.Sockets.$entry | Add-Member -MemberType NoteProperty -Name 'Threads' -Value $SocketList[$entry].ThreadCount; + $CpuData.Metrics.$entry | Add-Member -MemberType NoteProperty -Name 'Total' -Value $SocketList[$entry].TotalLoad; + } + + $CpuData.Metadata | Add-Member -MemberType NoteProperty -Name 'TotalLoad' -Value $TotalCpuLoad; + $CpuData.Metadata | Add-Member -MemberType NoteProperty -Name 'TotalThreads' -Value $TotalCpuThreads; + $CpuData.Metadata | Add-Member -MemberType NoteProperty -Name 'CoreDigits' -Value ([string]$TotalCpuThreads).Length; + $CpuData.Metadata | Add-Member -MemberType NoteProperty -Name 'CoreDetails' -Value (New-Object PSCustomObject); + + if ($IncludeDetails) { + [array]$CPUCIMData = Get-IcingaWindowsInformation Win32_Processor; + + foreach ($cpu in $CPUCIMData) { + if ((Test-PSCustomObjectMember -PSObject $CpuData.Metadata.CoreDetails -Name $cpu.DeviceID) -eq $FALSE) { + $CpuData.Metadata.CoreDetails | Add-Member -MemberType NoteProperty -Name $cpu.DeviceID -Value (New-Object PSCustomObject); + } + $CpuData.Metadata.CoreDetails.($cpu.DeviceID) | Add-Member -MemberType NoteProperty -Name 'Architecture' -Value $cpu.Architecture; + $CpuData.Metadata.CoreDetails.($cpu.DeviceID) | Add-Member -MemberType NoteProperty -Name 'ProcessorType' -Value $cpu.ProcessorType; + $CpuData.Metadata.CoreDetails.($cpu.DeviceID) | Add-Member -MemberType NoteProperty -Name 'StatusInfo' -Value $cpu.StatusInfo; + $CpuData.Metadata.CoreDetails.($cpu.DeviceID) | Add-Member -MemberType NoteProperty -Name 'Family' -Value $cpu.Family; + $CpuData.Metadata.CoreDetails.($cpu.DeviceID) | Add-Member -MemberType NoteProperty -Name 'CurrentVoltage' -Value $cpu.CurrentVoltage; + $CpuData.Metadata.CoreDetails.($cpu.DeviceID) | Add-Member -MemberType NoteProperty -Name 'L3CacheSize' -Value $cpu.L3CacheSize; + $CpuData.Metadata.CoreDetails.($cpu.DeviceID) | Add-Member -MemberType NoteProperty -Name 'L2CacheSize' -Value $cpu.L2CacheSize; + $CpuData.Metadata.CoreDetails.($cpu.DeviceID) | Add-Member -MemberType NoteProperty -Name 'L2CacheSpeed' -Value $cpu.L2CacheSpeed; + $CpuData.Metadata.CoreDetails.($cpu.DeviceID) | Add-Member -MemberType NoteProperty -Name 'VoltageCaps' -Value $cpu.VoltageCaps; + $CpuData.Metadata.CoreDetails.($cpu.DeviceID) | Add-Member -MemberType NoteProperty -Name 'CurrentClockSpeed' -Value $cpu.CurrentClockSpeed; + $CpuData.Metadata.CoreDetails.($cpu.DeviceID) | Add-Member -MemberType NoteProperty -Name 'Caption' -Value $cpu.Caption; + $CpuData.Metadata.CoreDetails.($cpu.DeviceID) | Add-Member -MemberType NoteProperty -Name 'Name' -Value $cpu.Name; + $CpuData.Metadata.CoreDetails.($cpu.DeviceID) | Add-Member -MemberType NoteProperty -Name 'SerialNumber' -Value $cpu.SerialNumber; + $CpuData.Metadata.CoreDetails.($cpu.DeviceID) | Add-Member -MemberType NoteProperty -Name 'Manufacturer' -Value $cpu.Manufacturer; + $CpuData.Metadata.CoreDetails.($cpu.DeviceID) | Add-Member -MemberType NoteProperty -Name 'AddressWidth' -Value $cpu.AddressWidth; + } + } + + return $CpuData; +} diff --git a/lib/provider/core/Get-IcingaProviderData.psm1 b/lib/provider/core/Get-IcingaProviderData.psm1 new file mode 100644 index 00000000..1c3acf74 --- /dev/null +++ b/lib/provider/core/Get-IcingaProviderData.psm1 @@ -0,0 +1,39 @@ +function Get-IcingaProviderData() +{ + param ( + [array]$Name = '' + ); + + [hashtable]$ProviderData = @{ }; + + foreach ($entry in $Name) { + [array]$ProviderDataList = Get-Command -Name ([string]::Format('Get-IcingaProviderDataValues{0}', $entry)) -ErrorAction SilentlyContinue; + + if ($null -eq $ProviderDataList -Or $ProviderDataList.Count -eq 0) { + $ProviderData.Add($entry, 'Provider not Found'); + continue; + } + + if ($ProviderDataList.Count -gt 1) { + $ProviderData.Add($entry, 'Provider name not unique enough'); + continue; + } + + if ((Test-IcingaForWindowsCmdletLoader -Path $ProviderDataList.Module.ModuleBase) -eq $FALSE) { + $ProviderData.Add($entry, 'Security violation. Provider not installed at Framework location'); + continue; + } + + $ProviderCmd = $ProviderDataList[0]; + + $ProviderContent = (& $ProviderCmd -IncludeDetails); + + if ($ProviderData.ContainsKey($ProviderContent.Name) -eq $FALSE) { + $ProviderData.Add($ProviderContent.Name, $ProviderContent); + } else { + $ProviderData[$ProviderContent.Name] = $ProviderContent; + } + } + + return $ProviderData; +} diff --git a/lib/provider/core/Get-IcingaProviderElement.psm1 b/lib/provider/core/Get-IcingaProviderElement.psm1 new file mode 100644 index 00000000..5f825aba --- /dev/null +++ b/lib/provider/core/Get-IcingaProviderElement.psm1 @@ -0,0 +1,18 @@ +function Get-IcingaProviderElement() +{ + param ( + $Object = $null + ); + + if ($null -eq $Object) { + return @(); + } + + try { + return $Object.PSObject.Properties + } catch { + return @(); + } + + return @(); +} diff --git a/lib/provider/core/New-IcingaProviderObject.psm1 b/lib/provider/core/New-IcingaProviderObject.psm1 new file mode 100644 index 00000000..26d591ac --- /dev/null +++ b/lib/provider/core/New-IcingaProviderObject.psm1 @@ -0,0 +1,17 @@ +function New-IcingaProviderObject() +{ + param ( + [string]$Name = 'Undefined' + ); + + $ProviderObject = New-Object PSCustomObject; + $ProviderObject | Add-Member -MemberType NoteProperty -Name 'Name' -Value $Name; + $ProviderObject | Add-Member -MemberType NoteProperty -Name 'Metadata' -Value (New-Object PSCustomObject); + $ProviderObject | Add-Member -MemberType NoteProperty -Name 'Metrics' -Value (New-Object PSCustomObject); + $ProviderObject | Add-Member -MemberType NoteProperty -Name 'MetricsOverTime' -Value (New-Object PSCustomObject); + $ProviderObject.MetricsOverTime | Add-Member -MemberType NoteProperty -Name 'MetricContainer' -Value (New-Object PSCustomObject); + $ProviderObject.MetricsOverTime | Add-Member -MemberType NoteProperty -Name 'Cache' -Value (New-Object PSCustomObject); + $ProviderObject.MetricsOverTime | Add-Member -MemberType NoteProperty -Name 'Compiled' -Value (New-Object PSCustomObject); + + return $ProviderObject; +}