diff --git a/lib/daemon/Start-IcingaPowerShellDaemon.psm1 b/lib/daemon/Start-IcingaPowerShellDaemon.psm1 new file mode 100644 index 0000000..fa8951d --- /dev/null +++ b/lib/daemon/Start-IcingaPowerShellDaemon.psm1 @@ -0,0 +1,27 @@ +function Start-IcingaPowerShellDaemon() +{ + $ScriptBlock = { + param($IcingaDaemonData); + + Use-Icinga -LibOnly -Daemon; + + try { + # Todo: Add dynamic loading of enabled background tasks + Start-IcingaServiceCheckDaemon; + } catch { + # Todo: Add exception handling + } + + while ($TRUE) { + Start-Sleep -Seconds 1; + } + }; + + $global:IcingaDaemonData.FrameworkRunningAsDaemon = $TRUE; + $global:IcingaDaemonData.Add('BackgroundDaemon', [hashtable]::Synchronized(@{})); + # Todo: Add config for active background tasks. Set it to 20 for the moment + $global:IcingaDaemonData.IcingaThreadPool.Add('BackgroundPool', (New-IcingaThreadPool -MaxInstances 20)); + $global:IcingaDaemonData.Add('Config', (Read-IcingaPowerShellConfig)); + + New-IcingaThreadInstance -Name "Icinga_PowerShell_Background_Daemon" -ThreadPool $IcingaDaemonData.IcingaThreadPool.BackgroundPool -ScriptBlock $ScriptBlock -Arguments @( $global:IcingaDaemonData ) -Start; +} diff --git a/lib/daemons/Start-IcingaServiceCheckDaemon.psm1 b/lib/daemons/Start-IcingaServiceCheckDaemon.psm1 new file mode 100644 index 0000000..5873cf8 --- /dev/null +++ b/lib/daemons/Start-IcingaServiceCheckDaemon.psm1 @@ -0,0 +1,107 @@ +function Start-IcingaServiceCheckDaemon() +{ + $ScriptBlock = { + param($IcingaDaemonData); + + Use-Icinga -LibOnly -Daemon; + + $IcingaDaemonData.BackgroundDaemon.Add('ServiceCheckScheduler', [hashtable]::Synchronized(@{})); + $IcingaDaemonData.IcingaThreadPool.Add('ServiceCheckPool', (New-IcingaThreadPool -MaxInstances (Get-IcingaConfigTreeCount -Path 'BackgroundDaemon.RegisteredServices'))); + + while ($TRUE) { + + $RegisteredServices = Get-IcingaRegisteredServiceChecks; + + foreach ($service in $RegisteredServices.Keys) { + [string]$ThreadName = [string]::Format('Icinga_Background_Service_Check_{0}', $service); + if ((Test-IcingaThread $ThreadName)) { + continue; + } + + Start-IcingaServiceCheckTask -CheckId $service -CheckCommand $RegisteredServices[$service].CheckCommand -Arguments $RegisteredServices[$service].Arguments -Interval $RegisteredServices[$service].Interval -TimeIndexes $RegisteredServices[$service].TimeIndexes; + } + Start-Sleep -Seconds 1; + } + }; + + New-IcingaThreadInstance -Name "Icinga_PowerShell_ServiceCheck_Scheduler" -ThreadPool $IcingaDaemonData.IcingaThreadPool.BackgroundPool -ScriptBlock $ScriptBlock -Arguments @( $global:IcingaDaemonData ) -Start; +} + +function Start-IcingaServiceCheckTask() +{ + param( + $CheckId, + $CheckCommand, + $Arguments, + $Interval, + $TimeIndexes + ); + + [string]$ThreadName = [string]::Format('Icinga_Background_Service_Check_{0}', $CheckId); + + $ScriptBlock = { + param($IcingaDaemonData, $CheckCommand, $Arguments, $Interval, $TimeIndexes, $CheckId); + + Use-Icinga -LibOnly -Daemon; + $PassedTime = 0; + + if (-Not ($IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler.ContainsKey($CheckCommand))) { + $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler.Add($CheckCommand, [hashtable]::Synchronized(@{})); + $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler[$CheckCommand].Add('results', [hashtable]::Synchronized(@{})); + $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler[$CheckCommand].Add('average', [hashtable]::Synchronized(@{})); + } + + while ($TRUE) { + if ($PassedTime -ge $Interval) { + & $CheckCommand @Arguments; + + $Results = $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler[$CheckCommand]['results']; + $UnixTime = Get-IcingaUnixTime; + $OldData = @{}; + + foreach ($result in $Results.Keys) { + $SortedResult = $Results[$result].GetEnumerator() | Sort-Object name -Descending; + Add-IcingaHashtableItem -Hashtable $OldData -Key $result -Value @{}; + + foreach ($index in $TimeIndexes) { + $ObjectCount = 0; + $ObjectValue = 0; + $TimeInSeconds = $index * 60; + + foreach ($timeEntry in $SortedResult) { + if (($UnixTime - $TimeInSeconds) -le [int]$timeEntry.Key) { + $ObjectCount += 1; + $ObjectValue += $timeEntry.Value; + Remove-IcingaHashtableItem -Hashtable $OldData[$result] -Key $timeEntry; + } else { + Add-IcingaHashtableItem -Hashtable $OldData[$result] -Key $timeEntry -Value $TRUE; + } + } + + $AvarageValue = ($ObjectValue / $ObjectCount); + $MetricName = [string]::Format('{0}_{1}', $result, $index); + + Add-IcingaHashtableItem ` + -Hashtable $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler[$CheckCommand]['average'] ` + -Key (Format-IcingaPerfDataLabel $MetricName) -Value $AvarageValue -Override; + } + } + + # Flush data we no longer require in our cache to free memory + foreach ($entry in $OldData.Keys) { + foreach ($key in $OldData[$entry].Keys) { + Remove-IcingaHashtableItem -Hashtable $Results[$entry] -Key $key + } + } + + Set-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult' -KeyName $CheckCommand -Value $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler[$CheckCommand]['average']; + + $PassedTime = 0; + } + $PassedTime += 1; + Start-Sleep -Seconds 1; + } + }; + + New-IcingaThreadInstance -Name $ThreadName -ThreadPool $IcingaDaemonData.IcingaThreadPool.ServiceCheckPool -ScriptBlock $ScriptBlock -Arguments @( $global:IcingaDaemonData, $CheckCommand, $Arguments, $Interval, $TimeIndexes, $CheckId ) -Start; +}