mirror of
https://github.com/Icinga/icinga-powershell-framework.git
synced 2025-12-21 23:29:40 -05:00
Merge pull request #414 from Icinga:fix/rewrite_service_check_daemon
Fix: Rewrite Icinga for Windows service check daemon Rewrite Icinga for Windows service check daemon for collecting metrics over time, to improve performance, decrease required resources and fix memory leaks.
This commit is contained in:
commit
c600a0fc68
84 changed files with 886 additions and 849 deletions
|
|
@ -20,6 +20,24 @@ After upgrading to Icinga for Windows v1.8.0, you will require to open a new Ici
|
||||||
|
|
||||||
**NOTE:** In some cases the changes for the EventLog will only apply, **after** the system has been rebooted. Afterwards every Icinga for Windows EventLog entry is written in a newly created `Icinga for Windows` log.
|
**NOTE:** In some cases the changes for the EventLog will only apply, **after** the system has been rebooted. Afterwards every Icinga for Windows EventLog entry is written in a newly created `Icinga for Windows` log.
|
||||||
|
|
||||||
|
### Custom Daemon Handling
|
||||||
|
|
||||||
|
With Icinga for Windows v1.8.0 we removed the entire list of currently available `$Global` variables:
|
||||||
|
|
||||||
|
* `$Global:IcingaThreads`
|
||||||
|
* `$Global:IcingaThreadContent`
|
||||||
|
* `$Global:IcingaThreadPool`
|
||||||
|
* `$Global:IcingaTimers`
|
||||||
|
* `$Global:IcingaDaemonData`
|
||||||
|
|
||||||
|
All of these have been centralized inside one, new variable called `$Global:Icinga`. You can read more about the structure of this `hashtable` object on the [Developer Guide](../900-Developer-Guide/00-General.md/#Data-Management).
|
||||||
|
|
||||||
|
The important change is, that in case you created custom daemons or API endpoints using on of the above globals, you will have to migrate your code to properly make use of `$Global:Icinga`, otherwise your daemons will not work anymore once you upgrade to Icinga for Windows v1.8.0.
|
||||||
|
|
||||||
|
The benefit of this change is that you no longer require to take care of synchronising global data between newly created threads, as Icinga for Windows will make the public part of `$Global:Icinga.Public` shared for every single instance automatically.
|
||||||
|
|
||||||
|
Please [contact us](https://icinga.com/company/contact/) in case you require assistance with migrating your current code to Icinga for Windows v1.8.0.
|
||||||
|
|
||||||
## Upgrading to v1.7.0 (2021-11-09)
|
## Upgrading to v1.7.0 (2021-11-09)
|
||||||
|
|
||||||
### REST-Api and Api-Checks
|
### REST-Api and Api-Checks
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
|
||||||
* [#409](https://github.com/Icinga/icinga-powershell-framework/issues/409) Fixes URL builder for `Sync-IcingaRepository` which will now properly test the JSON file and try a secondary fallback by pointing to the `ifw.repo.json` in case a URL is returning the directory listing instead
|
* [#409](https://github.com/Icinga/icinga-powershell-framework/issues/409) Fixes URL builder for `Sync-IcingaRepository` which will now properly test the JSON file and try a secondary fallback by pointing to the `ifw.repo.json` in case a URL is returning the directory listing instead
|
||||||
* [#411](https://github.com/Icinga/icinga-powershell-framework/pull/411) Fixes Icinga Director error message output because of missing `[string]::Format()`
|
* [#411](https://github.com/Icinga/icinga-powershell-framework/pull/411) Fixes Icinga Director error message output because of missing `[string]::Format()`
|
||||||
* [#412](https://github.com/Icinga/icinga-powershell-framework/issues/412) Fixes possible defective state of the Icinga Agent by using a custom service user for JEA profiles which is larger than 20 digits
|
* [#412](https://github.com/Icinga/icinga-powershell-framework/issues/412) Fixes possible defective state of the Icinga Agent by using a custom service user for JEA profiles which is larger than 20 digits
|
||||||
|
* [#414](https://github.com/Icinga/icinga-powershell-framework/pull/414) Fixes Service Check Daemon with a total rewrite to improve performance, decrease required resources and fix memory leaks
|
||||||
* [#418](https://github.com/Icinga/icinga-powershell-framework/pull/418) Fixes crash on wrong variable usage introduced by [#411](https://github.com/Icinga/icinga-powershell-framework/pull/411)
|
* [#418](https://github.com/Icinga/icinga-powershell-framework/pull/418) Fixes crash on wrong variable usage introduced by [#411](https://github.com/Icinga/icinga-powershell-framework/pull/411)
|
||||||
* [#421](https://github.com/Icinga/icinga-powershell-framework/issues/421) Fixes experimental state of `API Check` feature by removing that term and removing the requirement to install `icinga-powershell-restapi` and `icinga-powershell-apichecks`
|
* [#421](https://github.com/Icinga/icinga-powershell-framework/issues/421) Fixes experimental state of `API Check` feature by removing that term and removing the requirement to install `icinga-powershell-restapi` and `icinga-powershell-apichecks`
|
||||||
* [#436](https://github.com/Icinga/icinga-powershell-framework/pull/436) Fixes a lookup error for existing plugin documentation files, which caused files not being generated properly in case a similar name was already present on the system
|
* [#436](https://github.com/Icinga/icinga-powershell-framework/pull/436) Fixes a lookup error for existing plugin documentation files, which caused files not being generated properly in case a similar name was already present on the system
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,81 @@ In this case, our `NestedModules` variable within our `.psd1` file requires the
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Data Management
|
||||||
|
|
||||||
|
Icinga for Windows is using one global variable `$Global:Icinga`, to store information for daemons and other tasks. This variable is split into three different categories, which you can read more on below. The general architecture of this construct is a simple `hashtable`.
|
||||||
|
You can interact with this variable and sub-entries like you would with normal `hashtables`, making data stored a lot easier to access and maintain.
|
||||||
|
|
||||||
|
#### Private
|
||||||
|
|
||||||
|
Everything which should be stored while a daemon is running internally or within a PowerShell session and **not** being shared with other daemons, is stored within the `$Global:Icinga.Private` space.
|
||||||
|
|
||||||
|
The following entries are set by default within the `Private` space:
|
||||||
|
|
||||||
|
| Category | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| Timers | All created timers by using `Start-IcingaTimer` are stored under this environment variable |
|
||||||
|
| Scheduler | Once plugins are executed, performance data, check results and exit codes are stored in this section, in case the PowerShell instance is set to run as daemon |
|
||||||
|
| Daemons | This is a place where all daemon data should be added and stored, separated by a namespace for each module as entry. This data is **not** shared between other daemons |
|
||||||
|
|
||||||
|
#### Example Data
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$Global:Icinga.Private.Timers.DefaultTimer
|
||||||
|
```
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$Global:Icinga.Private.Scheduler.CheckResults
|
||||||
|
```
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.PerformanceCache
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Public
|
||||||
|
|
||||||
|
Everything stored within the `Public` space of `$Global:Icinga` is automatically shared between all threads of the current PowerShell instance. If you run the `ServiceCheckDaemon` in addition with the `RestAPI` for example, metrics over time will be read from the public shared space from the `RestApi` and used during check execution.
|
||||||
|
|
||||||
|
There is no manual configuration required to share the information, as Icinga for Windows will deal with this for you, once a new thread instance is created.
|
||||||
|
|
||||||
|
The following entries are set by default within the `Public` space:
|
||||||
|
|
||||||
|
| Category | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| ThreadPools | A list of all thread pools available to create new thread limits for certain background daemons |
|
||||||
|
| Daemons | A place to store shared information for each single daemon within a namespace, making data accessible to other threads |
|
||||||
|
| Threads | A list of all started and available threads running by Icinga for Windows |
|
||||||
|
| PerformanceCounter | A space to share all PerformanceCounter information between threads, which counters are already created for internal usage |
|
||||||
|
|
||||||
|
##### Example Data
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$Global:Icinga.Public.ThreadPools.MainPool
|
||||||
|
```
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$Global:Icinga.Public.Daemons.RESTApi.ClientBlacklist
|
||||||
|
```
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$Global:Icinga.Public.Threads.'Start-IcingaForWindowsDaemon::Add-IcingaForWindowsDaemon::Main::0'
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Protected
|
||||||
|
|
||||||
|
This is a section reserved for Icinga for Windows and Icinga developers in general. This space will store general information for Icinga for Windows, determining on how the PowerShell instance is handling internal requests and procedures.
|
||||||
|
|
||||||
|
As custom module developer, you can **read** from this space but are in genetal **not** allowed to store information there. Please use the `Private` and `Public` space for this.
|
||||||
|
|
||||||
|
The following entries are set by default within the `Protected` space:
|
||||||
|
|
||||||
|
| Category | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| JEAContext | Tells Icinga for Windows that the current environment is running within a JEA context |
|
||||||
|
| RunAsDaemon | Tells Icinga for Windows that the current PowerShell instance is running as daemon, changing behaviors on error and plugin execution handling |
|
||||||
|
| DebugMode | Enables the debug mode of Icinga for Windows, printing additional details during operations or tasks |
|
||||||
|
| Minimal | Changes certain behavior regarding check execution and internal error handling |
|
||||||
|
|
||||||
## Using Icinga for Windows Dev Tools
|
## Using Icinga for Windows Dev Tools
|
||||||
|
|
||||||
Maintaining the entire structure above seems to be complicated at the beginning, especially when considering to update the `NestedModules` section whenever you make changes. To mitigate this, Icinga for Windows provides a bunch of Cmdlets to help with the process
|
Maintaining the entire structure above seems to be complicated at the beginning, especially when considering to update the `NestedModules` section whenever you make changes. To mitigate this, Icinga for Windows provides a bunch of Cmdlets to help with the process
|
||||||
|
|
|
||||||
|
|
@ -94,18 +94,13 @@ function Add-IcingaAgentServiceTest()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Depending on our daemon, later usage and possible sharing of data between all loaded daemons might be required. In addition we might want to spawn child threads as single tasks being executed. To do so, we will parse the frameworks `global` data to the thread.
|
Depending on our daemon, later usage and possible sharing of data between all loaded daemons might be required. In addition we might want to spawn child threads as single tasks being executed. To access the global, shared data, use can use the `Global:Icinga.Public` variable. This content is shared automatically between each single created thread.
|
||||||
|
|
||||||
Our recommendation is to always do this for every daemon, as later changes might be more complicated and time consuming.
|
Our recommendation is to always do this for every daemon, as later changes might be more complicated and time consuming.
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
function Add-IcingaAgentServiceTest()
|
function Add-IcingaAgentServiceTest()
|
||||||
{
|
{
|
||||||
# Allow us to parse the framework global data to this thread
|
|
||||||
param (
|
|
||||||
$IcingaDaemonData
|
|
||||||
);
|
|
||||||
|
|
||||||
# Everything which will be executed inside the thread
|
# Everything which will be executed inside the thread
|
||||||
# belongs here
|
# belongs here
|
||||||
}
|
}
|
||||||
|
|
@ -116,11 +111,6 @@ Now as the basic part is finished, we will require to make our framework librari
|
||||||
```powershell
|
```powershell
|
||||||
function Add-IcingaAgentServiceTest()
|
function Add-IcingaAgentServiceTest()
|
||||||
{
|
{
|
||||||
# Allow us to parse the framework global data to this thread
|
|
||||||
param (
|
|
||||||
$IcingaDaemonData
|
|
||||||
);
|
|
||||||
|
|
||||||
# Import the framework library components and initialise it
|
# Import the framework library components and initialise it
|
||||||
# as daemon
|
# as daemon
|
||||||
Use-Icinga -LibOnly -Daemon;
|
Use-Icinga -LibOnly -Daemon;
|
||||||
|
|
@ -132,29 +122,19 @@ As we will parse the `global` framework data anyways, we should already make use
|
||||||
```powershell
|
```powershell
|
||||||
function Add-IcingaAgentServiceTest()
|
function Add-IcingaAgentServiceTest()
|
||||||
{
|
{
|
||||||
# Allow us to parse the framework global data to this thread
|
|
||||||
param (
|
|
||||||
$IcingaDaemonData
|
|
||||||
);
|
|
||||||
|
|
||||||
# Import the framework library components and initialise it
|
# Import the framework library components and initialise it
|
||||||
# as daemon
|
# as daemon
|
||||||
Use-Icinga -LibOnly -Daemon;
|
Use-Icinga -LibOnly -Daemon;
|
||||||
|
|
||||||
# Add a synchronized hashtable to the global data background
|
# Add a hashtable to the public data background
|
||||||
# daemon hashtable to write data to. In addition it will
|
# daemon hashtable to write data to. In addition it will
|
||||||
# allow to share data collected from this daemon with others
|
# allow to share data collected from this daemon with others
|
||||||
$IcingaDaemonData.BackgroundDaemon.Add(
|
$Global:Icinga.Public.Daemons.Add('TestIcingaAgentService', @{ });
|
||||||
'TestIcingaAgentService',
|
|
||||||
[hashtable]::Synchronized(@{ })
|
|
||||||
);
|
|
||||||
# This will add another hashtable to our previous
|
# This will add another hashtable to our previous
|
||||||
# TestIcingaAgentService hashtable to store actual service
|
# TestIcingaAgentService hashtable to store actual service
|
||||||
# information
|
# information
|
||||||
$IcingaDaemonData.BackgroundDaemon.TestIcingaAgentService.Add(
|
$Global:Icinga.Public.Daemons.TestIcingaAgentService.Add('ServiceState', @{ });
|
||||||
'ServiceState',
|
|
||||||
[hashtable]::Synchronized(@{ })
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -165,29 +145,19 @@ Because the code is executed as separate thread, we will have to ensure it will
|
||||||
```powershell
|
```powershell
|
||||||
function Add-IcingaAgentServiceTest()
|
function Add-IcingaAgentServiceTest()
|
||||||
{
|
{
|
||||||
# Allow us to parse the framework global data to this thread
|
|
||||||
param (
|
|
||||||
$IcingaDaemonData
|
|
||||||
);
|
|
||||||
|
|
||||||
# Import the framework library components and initialise it
|
# Import the framework library components and initialise it
|
||||||
# as daemon
|
# as daemon
|
||||||
Use-Icinga -LibOnly -Daemon;
|
Use-Icinga -LibOnly -Daemon;
|
||||||
|
|
||||||
# Add a synchronized hashtable to the global data background
|
# Add a hashtable to the public data background
|
||||||
# daemon hashtable to write data to. In addition it will
|
# daemon hashtable to write data to. In addition it will
|
||||||
# allow to share data collected from this daemon with others
|
# allow to share data collected from this daemon with others
|
||||||
$IcingaDaemonData.BackgroundDaemon.Add(
|
$Global:Icinga.Public.Daemons.Add('TestIcingaAgentService', @{ });
|
||||||
'TestIcingaAgentService',
|
|
||||||
[hashtable]::Synchronized(@{ })
|
|
||||||
);
|
|
||||||
# This will add another hashtable to our previous
|
# This will add another hashtable to our previous
|
||||||
# TestIcingaAgentService hashtable to store actual service
|
# TestIcingaAgentService hashtable to store actual service
|
||||||
# information
|
# information
|
||||||
$IcingaDaemonData.BackgroundDaemon.TestIcingaAgentService.Add(
|
$Global:Icinga.Public.Daemons.TestIcingaAgentService.Add('ServiceState', @{ });
|
||||||
'ServiceState',
|
|
||||||
[hashtable]::Synchronized(@{ })
|
|
||||||
);
|
|
||||||
|
|
||||||
# Keep our code executed as long as the PowerShell service is
|
# Keep our code executed as long as the PowerShell service is
|
||||||
# being executed. This is required to ensure we will execute
|
# being executed. This is required to ensure we will execute
|
||||||
|
|
@ -197,34 +167,24 @@ function Add-IcingaAgentServiceTest()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
*ALWAYS* ensure you add some sort for `sleep` at the end of the `while` loop to allow your CPU some breaks. If you do not do this, you might suffer from high CPU loads. The `sleep duration` interval can depend either on a simple CPU cycle break or by telling the daemon to execute tasks only in certain interval. In our case we wish to execute the daemon every `5 seconds`.
|
*ALWAYS* ensure you add some sort for `sleep` at the end of the `while` loop to allow your CPU some breaks. If you do not do this, you might suffer from high CPU loads. The `sleep duration` interval can depend either on a simple CPU cycle break or by telling the daemon to execute tasks only in certain Intervalls. In our case we wish to execute the daemon every `5 seconds`.
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
function Add-IcingaAgentServiceTest()
|
function Add-IcingaAgentServiceTest()
|
||||||
{
|
{
|
||||||
# Allow us to parse the framework global data to this thread
|
|
||||||
param (
|
|
||||||
$IcingaDaemonData
|
|
||||||
);
|
|
||||||
|
|
||||||
# Import the framework library components and initialise it
|
# Import the framework library components and initialise it
|
||||||
# as daemon
|
# as daemon
|
||||||
Use-Icinga -LibOnly -Daemon;
|
Use-Icinga -LibOnly -Daemon;
|
||||||
|
|
||||||
# Add a synchronized hashtable to the global data background
|
# Add a hashtable to the public data background
|
||||||
# daemon hashtable to write data to. In addition it will
|
# daemon hashtable to write data to. In addition it will
|
||||||
# allow to share data collected from this daemon with others
|
# allow to share data collected from this daemon with others
|
||||||
$IcingaDaemonData.BackgroundDaemon.Add(
|
$Global:Icinga.Public.Daemons.Add('TestIcingaAgentService', @{ });
|
||||||
'TestIcingaAgentService',
|
|
||||||
[hashtable]::Synchronized(@{ })
|
|
||||||
);
|
|
||||||
# This will add another hashtable to our previous
|
# This will add another hashtable to our previous
|
||||||
# TestIcingaAgentService hashtable to store actual service
|
# TestIcingaAgentService hashtable to store actual service
|
||||||
# information
|
# information
|
||||||
$IcingaDaemonData.BackgroundDaemon.TestIcingaAgentService.Add(
|
$Global:Icinga.Public.Daemons.TestIcingaAgentService.Add('ServiceState', @{ });
|
||||||
'ServiceState',
|
|
||||||
[hashtable]::Synchronized(@{ })
|
|
||||||
);
|
|
||||||
|
|
||||||
# Keep our code executed as long as the PowerShell service is
|
# Keep our code executed as long as the PowerShell service is
|
||||||
# being executed. This is required to ensure we will execute
|
# being executed. This is required to ensure we will execute
|
||||||
|
|
@ -243,29 +203,19 @@ This is basically the foundation of every single daemon you will write. Now we w
|
||||||
```powershell
|
```powershell
|
||||||
function Add-IcingaAgentServiceTest()
|
function Add-IcingaAgentServiceTest()
|
||||||
{
|
{
|
||||||
# Allow us to parse the framework global data to this thread
|
|
||||||
param (
|
|
||||||
$IcingaDaemonData
|
|
||||||
);
|
|
||||||
|
|
||||||
# Import the framework library components and initialise it
|
# Import the framework library components and initialise it
|
||||||
# as daemon
|
# as daemon
|
||||||
Use-Icinga -LibOnly -Daemon;
|
Use-Icinga -LibOnly -Daemon;
|
||||||
|
|
||||||
# Add a synchronized hashtable to the global data background
|
# Add a hashtable to the public data background
|
||||||
# daemon hashtable to write data to. In addition it will
|
# daemon hashtable to write data to. In addition it will
|
||||||
# allow to share data collected from this daemon with others
|
# allow to share data collected from this daemon with others
|
||||||
$IcingaDaemonData.BackgroundDaemon.Add(
|
$Global:Icinga.Public.Daemons.Add('TestIcingaAgentService', @{ });
|
||||||
'TestIcingaAgentService',
|
|
||||||
[hashtable]::Synchronized(@{ })
|
|
||||||
);
|
|
||||||
# This will add another hashtable to our previous
|
# This will add another hashtable to our previous
|
||||||
# TestIcingaAgentService hashtable to store actual service
|
# TestIcingaAgentService hashtable to store actual service
|
||||||
# information
|
# information
|
||||||
$IcingaDaemonData.BackgroundDaemon.TestIcingaAgentService.Add(
|
$Global:Icinga.Public.Daemons.TestIcingaAgentService.Add('ServiceState', @{ });
|
||||||
'ServiceState',
|
|
||||||
[hashtable]::Synchronized(@{ })
|
|
||||||
);
|
|
||||||
|
|
||||||
# Initialise our error counter variable
|
# Initialise our error counter variable
|
||||||
[int]$RestartErrors = 0;
|
[int]$RestartErrors = 0;
|
||||||
|
|
@ -283,7 +233,7 @@ function Add-IcingaAgentServiceTest()
|
||||||
if ($null -ne $ServiceState) {
|
if ($null -ne $ServiceState) {
|
||||||
# Add the current service state to our hashtable.
|
# Add the current service state to our hashtable.
|
||||||
Add-IcingaHashtableItem `
|
Add-IcingaHashtableItem `
|
||||||
-Hashtable $IcingaDaemonData.BackgroundDaemon.TestIcingaAgentService.ServiceState `
|
-Hashtable $Global:Icinga.Public.Daemons.TestIcingaAgentService.ServiceState `
|
||||||
-Key 'value' `
|
-Key 'value' `
|
||||||
-Value $ServiceState.Status `
|
-Value $ServiceState.Status `
|
||||||
-Override | Out-Null;
|
-Override | Out-Null;
|
||||||
|
|
@ -295,7 +245,7 @@ function Add-IcingaAgentServiceTest()
|
||||||
Restart-Service 'icinga2' -ErrorAction Stop;
|
Restart-Service 'icinga2' -ErrorAction Stop;
|
||||||
|
|
||||||
Add-IcingaHashtableItem `
|
Add-IcingaHashtableItem `
|
||||||
-Hashtable $IcingaDaemonData.BackgroundDaemon.TestIcingaAgentService.ServiceState `
|
-Hashtable $Global:Icinga.Public.Daemons.TestIcingaAgentService.ServiceState `
|
||||||
-Key 'restart_error' `
|
-Key 'restart_error' `
|
||||||
-Value 0 `
|
-Value 0 `
|
||||||
-Override | Out-Null;
|
-Override | Out-Null;
|
||||||
|
|
@ -303,7 +253,7 @@ function Add-IcingaAgentServiceTest()
|
||||||
# Add an error counter in case we failed
|
# Add an error counter in case we failed
|
||||||
$RestartErrors += 1;
|
$RestartErrors += 1;
|
||||||
Add-IcingaHashtableItem `
|
Add-IcingaHashtableItem `
|
||||||
-Hashtable $IcingaDaemonData.BackgroundDaemon.TestIcingaAgentService.ServiceState `
|
-Hashtable $Global:Icinga.Public.Daemons.TestIcingaAgentService.ServiceState `
|
||||||
-Key 'restart_error' `
|
-Key 'restart_error' `
|
||||||
-Value $RestartErrors `
|
-Value $RestartErrors `
|
||||||
-Override | Out-Null;
|
-Override | Out-Null;
|
||||||
|
|
@ -322,7 +272,7 @@ function Add-IcingaAgentServiceTest()
|
||||||
|
|
||||||
Once our function is completed we only require to call it once our daemon is registered. Do to so, we will use the Cmdlet `New-IcingaThreadInstance`.
|
Once our function is completed we only require to call it once our daemon is registered. Do to so, we will use the Cmdlet `New-IcingaThreadInstance`.
|
||||||
|
|
||||||
As arguments we will have to add a unique `name` to use for this thread as well as a `thread pool`, on which the function will be added to. In our case we will use the Frameworks default pool. Last but not least we require to parse possible `Arguments` to our function and tell the thread to `Start` right after being created. For the arguments we will parse the frameworks `global` `IcingaDaemonData` we also use inside our function to store data in.
|
As arguments we will have to add a unique `name` to use for this thread as well as a `thread pool`, on which the function will be added to. The name of the thread is automatically constructed based on the caller function, the function being executed and the given name. If you create a thread which is used as a `main` thread for several sub-threads, you could call it `Main`. For our example, the constructed thread name will then internally be `Start-IcingaAgentServiceTest::IcingaAgentServiceTest::Main::0`. The last added digit will auto increment, in case you are adding the identical thread multiple times, allowing you to access certain threads again by their index id. For the thread pool, we will use the default thread pool `MainPool` of Icinga for Windows. To customize this, you can use `Add-IcingaThreadPool` with a unique name and the amount if allowed instances. Last but not least we require to parse possible `Arguments` to our function and tell the thread to `Start` right after being created.
|
||||||
|
|
||||||
This call will be added inside the `Start-IcingaAgentServiceTest` we created earlier and didn't touch so far yet.
|
This call will be added inside the `Start-IcingaAgentServiceTest` we created earlier and didn't touch so far yet.
|
||||||
|
|
||||||
|
|
@ -333,12 +283,10 @@ function Start-IcingaAgentServiceTest()
|
||||||
# function as command to call it and parse all our
|
# function as command to call it and parse all our
|
||||||
# arguments to it
|
# arguments to it
|
||||||
New-IcingaThreadInstance `
|
New-IcingaThreadInstance `
|
||||||
-Name 'Icinga_PowerShell_IcingaAgent_StateCheck' `
|
-Name 'Main' `
|
||||||
-ThreadPool $global:IcingaDaemonData.IcingaThreadPool.BackgroundPool `
|
-ThreadPool (Get-IcingaThreadPool -Name 'MainPool') `
|
||||||
-Command 'Add-IcingaAgentServiceTest' `
|
-Command 'Add-IcingaAgentServiceTest' `
|
||||||
-CmdParameters @{
|
-CmdParameters @{ } `
|
||||||
'IcingaDaemonData' = $global:IcingaDaemonData;
|
|
||||||
} `
|
|
||||||
-Start;
|
-Start;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -368,13 +316,13 @@ Once the service is stopped and your `administrative PowerShell` is open, we wil
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
Use-Icinga;
|
Use-Icinga;
|
||||||
Start-IcingaPowerShellDaemon;
|
Start-IcingaForWindowsDaemon;
|
||||||
```
|
```
|
||||||
|
|
||||||
Once done you will receive back your prompt, however all registered background daemons are running. To access the collected data from daemons, you can print the content of the `global` framework data. If you wish to check if your daemon was loaded properly and data is actually written, we can access our created hashtable and get the current service state of it
|
Once done you will receive back your prompt, however all registered background daemons are running. To access the collected data from daemons, you can print the content of the `global` framework data. If you wish to check if your daemon was loaded properly and data is actually written, we can access our created hashtable and get the current service state of it
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
$global:IcingaDaemonData.BackgroundDaemon.TestIcingaAgentService.ServiceState['value'];
|
$Global:Icinga.Public.Daemons.TestIcingaAgentService.ServiceState['value'];
|
||||||
```
|
```
|
||||||
|
|
||||||
In case your Icinga Agent service is installed and your daemon is running properly, this should print the current state of the service.
|
In case your Icinga Agent service is installed and your daemon is running properly, this should print the current state of the service.
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,6 @@ function Invoke-IcingaAPITutorialRESTCall()
|
||||||
param (
|
param (
|
||||||
[Hashtable]$Request = @{ },
|
[Hashtable]$Request = @{ },
|
||||||
[Hashtable]$Connection = @{ },
|
[Hashtable]$Connection = @{ },
|
||||||
$IcingaGlobals,
|
|
||||||
[string]$ApiVersion = $null
|
[string]$ApiVersion = $null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -187,10 +186,6 @@ This only applies to any request which can send data as body and tells you how m
|
||||||
|
|
||||||
This argument is containing the connection details of the client including the TCP stream object. You only require this for sending data back to the client or for troubleshooting. In general you only have to parse this object to other functions without modifying it.
|
This argument is containing the connection details of the client including the TCP stream object. You only require this for sending data back to the client or for troubleshooting. In general you only have to parse this object to other functions without modifying it.
|
||||||
|
|
||||||
#### IcingaGlobals Argument
|
|
||||||
|
|
||||||
This argument contains all global data and content of the REST-Api background daemon. This will then come in handy to share data between API endpoints and to access some global configuration data.
|
|
||||||
|
|
||||||
### Sending Data to the Client
|
### Sending Data to the Client
|
||||||
|
|
||||||
Now we are basically ready to process data. To do so, we will fetch the current folder content of our PowerShell module with `Get-ChildItem` and send this content to our client. For sending data to the client, we can use `Send-IcingaTCPClientMessage`. This Cmdlet will use a `Message` as `New-IcingaTCPClientRESTMessage` object which itself contains the `HTTPResponse` and our `ContentBody`. In addition to `Send-IcingaTCPClientMessage` we also have to specify the `Stream` to write to. The stream object is part of our `Connection` argument.
|
Now we are basically ready to process data. To do so, we will fetch the current folder content of our PowerShell module with `Get-ChildItem` and send this content to our client. For sending data to the client, we can use `Send-IcingaTCPClientMessage`. This Cmdlet will use a `Message` as `New-IcingaTCPClientRESTMessage` object which itself contains the `HTTPResponse` and our `ContentBody`. In addition to `Send-IcingaTCPClientMessage` we also have to specify the `Stream` to write to. The stream object is part of our `Connection` argument.
|
||||||
|
|
@ -204,7 +199,6 @@ function Invoke-IcingaAPITutorialRESTCall()
|
||||||
param (
|
param (
|
||||||
[Hashtable]$Request = @{ },
|
[Hashtable]$Request = @{ },
|
||||||
[Hashtable]$Connection = @{ },
|
[Hashtable]$Connection = @{ },
|
||||||
$IcingaGlobals,
|
|
||||||
[string]$ApiVersion = $null
|
[string]$ApiVersion = $null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,15 +31,10 @@ function Use-Icinga()
|
||||||
}
|
}
|
||||||
|
|
||||||
Disable-IcingaProgressPreference;
|
Disable-IcingaProgressPreference;
|
||||||
|
New-IcingaEnvironmentVariable;
|
||||||
|
|
||||||
if ($Minimal) {
|
if ($Minimal) {
|
||||||
if ($null -eq $global:Icinga) {
|
$Global:Icinga.Protected.Minimal = $TRUE;
|
||||||
$global:Icinga = @{ };
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($global:Icinga.ContainsKey('Minimal') -eq $FALSE) {
|
|
||||||
$global:Icinga.Add('Minimal', $TRUE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ensure we autoload the Icinga Plugin collection, provided by the external
|
# Ensure we autoload the Icinga Plugin collection, provided by the external
|
||||||
|
|
@ -48,50 +43,23 @@ function Use-Icinga()
|
||||||
Use-IcingaPlugins;
|
Use-IcingaPlugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($LibOnly -eq $FALSE) {
|
if ($Daemon) {
|
||||||
$global:IcingaThreads = [hashtable]::Synchronized(@{ });
|
$Global:Icinga.Protected.RunAsDaemon = $TRUE;
|
||||||
$global:IcingaThreadContent = [hashtable]::Synchronized(@{ });
|
}
|
||||||
$global:IcingaThreadPool = [hashtable]::Synchronized(@{ });
|
|
||||||
$global:IcingaTimers = [hashtable]::Synchronized(@{ });
|
if ($DebugMode) {
|
||||||
$global:IcingaDaemonData = [hashtable]::Synchronized(
|
$Global:Icinga.Protected.DebugMode = $TRUE;
|
||||||
@{
|
|
||||||
'IcingaThreads' = $global:IcingaThreads;
|
|
||||||
'IcingaThreadContent' = $global:IcingaThreadContent;
|
|
||||||
'IcingaThreadPool' = $global:IcingaThreadPool;
|
|
||||||
'IcingaTimers' = $global:IcingaTimers;
|
|
||||||
'FrameworkRunningAsDaemon' = $Daemon;
|
|
||||||
'JEAContext' = $FALSE;
|
|
||||||
'DebugMode' = $DebugMode;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
# This will fix the debug mode in case we are only using Libs
|
|
||||||
# without any other variable content and daemon handling
|
|
||||||
if ($null -eq $global:IcingaDaemonData) {
|
|
||||||
$global:IcingaDaemonData = [hashtable]::Synchronized(@{ });
|
|
||||||
}
|
|
||||||
if ($global:IcingaDaemonData.ContainsKey('DebugMode') -eq $FALSE) {
|
|
||||||
$global:IcingaDaemonData.DebugMode = $DebugMode;
|
|
||||||
}
|
|
||||||
if ($global:IcingaDaemonData.ContainsKey('JEAContext') -eq $FALSE) {
|
|
||||||
$global:IcingaDaemonData.JEAContext = $FALSE;
|
|
||||||
}
|
|
||||||
if ($global:IcingaDaemonData.ContainsKey('FrameworkRunningAsDaemon') -eq $FALSE) {
|
|
||||||
$global:IcingaDaemonData.FrameworkRunningAsDaemon = $Daemon;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
New-IcingaPerformanceCounterCache;
|
|
||||||
|
|
||||||
# Enable DebugMode in case it is enabled in our config
|
# Enable DebugMode in case it is enabled in our config
|
||||||
if (Get-IcingaFrameworkDebugMode) {
|
if (Get-IcingaFrameworkDebugMode) {
|
||||||
Enable-IcingaFrameworkDebugMode;
|
Enable-IcingaFrameworkDebugMode;
|
||||||
$DebugMode = $TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$EventLogMessages = Invoke-IcingaNamespaceCmdlets -Command 'Register-IcingaEventLogMessages*';
|
$EventLogMessages = Invoke-IcingaNamespaceCmdlets -Command 'Register-IcingaEventLogMessages*';
|
||||||
foreach ($entry in $EventLogMessages.Values) {
|
foreach ($entry in $EventLogMessages.Values) {
|
||||||
foreach ($event in $entry.Keys) {
|
foreach ($event in $entry.Keys) {
|
||||||
if ($LibOnly -eq $FALSE) {
|
if ($LibOnly -eq $FALSE -And $Daemon -eq $FALSE) {
|
||||||
Register-IcingaEventLog -LogName $event;
|
Register-IcingaEventLog -LogName $event;
|
||||||
}
|
}
|
||||||
Add-IcingaHashtableItem -Hashtable $global:IcingaEventLogEnums `
|
Add-IcingaHashtableItem -Hashtable $global:IcingaEventLogEnums `
|
||||||
|
|
@ -100,7 +68,7 @@ function Use-Icinga()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($LibOnly -eq $FALSE) {
|
if ($LibOnly -eq $FALSE -And $Daemon -eq $FALSE) {
|
||||||
Register-IcingaEventLog;
|
Register-IcingaEventLog;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
function Get-IcingaPowerShellConfig()
|
function Get-IcingaPowerShellConfig()
|
||||||
{
|
{
|
||||||
param(
|
param (
|
||||||
$Path = ''
|
$Path = ''
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ function Read-IcingaPowerShellConfig()
|
||||||
Move-Item -Path $ConfigFile -Destination $NewConfigFile -ErrorAction SilentlyContinue;
|
Move-Item -Path $ConfigFile -Destination $NewConfigFile -ErrorAction SilentlyContinue;
|
||||||
New-Item -ItemType File -Path $ConfigFile -ErrorAction SilentlyContinue;
|
New-Item -ItemType File -Path $ConfigFile -ErrorAction SilentlyContinue;
|
||||||
|
|
||||||
Write-IcingaEventMessage -EventId 1100 -Namespace 'Framework' -Objects $ConfigFile, $Content;
|
Write-IcingaEventMessage -EventId 1100 -Namespace 'Framework' -ExceptionObject $_ -Objects $ConfigFile, $Content;
|
||||||
Write-IcingaConsoleError -Message 'Your configuration file "{0}" was corrupt and could not be read. It was moved to "{1}" for review and a new plain file has been created' -Objects $ConfigFile, $NewConfigFile;
|
Write-IcingaConsoleError -Message 'Your configuration file "{0}" was corrupt and could not be read. It was moved to "{1}" for review and a new plain file has been created' -Objects $ConfigFile, $NewConfigFile;
|
||||||
|
|
||||||
$ConfigObject = (New-Object -TypeName PSObject);
|
$ConfigObject = (New-Object -TypeName PSObject);
|
||||||
|
|
|
||||||
|
|
@ -101,14 +101,11 @@ function New-IcingaForWindowsComponent()
|
||||||
Add-Content -Path $InvokeFunctionFile -Value '{';
|
Add-Content -Path $InvokeFunctionFile -Value '{';
|
||||||
Add-Content -Path $InvokeFunctionFile -Value ' # Do not modify the param section';
|
Add-Content -Path $InvokeFunctionFile -Value ' # Do not modify the param section';
|
||||||
Add-Content -Path $InvokeFunctionFile -Value ' param (';
|
Add-Content -Path $InvokeFunctionFile -Value ' param (';
|
||||||
Add-Content -Path $InvokeFunctionFile -Value ' [Hashtable]$Request = @{ },';
|
Add-Content -Path $InvokeFunctionFile -Value ' [Hashtable]$Request = @{},';
|
||||||
Add-Content -Path $InvokeFunctionFile -Value ' [Hashtable]$Connection = @{ },';
|
Add-Content -Path $InvokeFunctionFile -Value ' [Hashtable]$Connection = @{},';
|
||||||
Add-Content -Path $InvokeFunctionFile -Value ' $IcingaGlobals,';
|
|
||||||
Add-Content -Path $InvokeFunctionFile -Value ' [string]$ApiVersion = $null';
|
Add-Content -Path $InvokeFunctionFile -Value ' [string]$ApiVersion = $null';
|
||||||
Add-Content -Path $InvokeFunctionFile -Value ' );'
|
Add-Content -Path $InvokeFunctionFile -Value ' );'
|
||||||
Add-Content -Path $InvokeFunctionFile -Value '';
|
Add-Content -Path $InvokeFunctionFile -Value '';
|
||||||
Add-Content -Path $InvokeFunctionFile -Value ' $Global:IcingaDaemonData = $IcingaGlobals;';
|
|
||||||
Add-Content -Path $InvokeFunctionFile -Value '';
|
|
||||||
Add-Content -Path $InvokeFunctionFile -Value ' # This is the main function for your API endpoint.';
|
Add-Content -Path $InvokeFunctionFile -Value ' # This is the main function for your API endpoint.';
|
||||||
Add-Content -Path $InvokeFunctionFile -Value ' # Also check the developer guide for further details: https://icinga.com/docs/icinga-for-windows/latest/doc/900-Developer-Guide/12-Custom-API-Endpoints/';
|
Add-Content -Path $InvokeFunctionFile -Value ' # Also check the developer guide for further details: https://icinga.com/docs/icinga-for-windows/latest/doc/900-Developer-Guide/12-Custom-API-Endpoints/';
|
||||||
Add-Content -Path $InvokeFunctionFile -Value '';
|
Add-Content -Path $InvokeFunctionFile -Value '';
|
||||||
|
|
@ -147,7 +144,12 @@ function New-IcingaForWindowsComponent()
|
||||||
"'"
|
"'"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value ' -ThreadPool $IcingaDaemonData.IcingaThreadPool.BackgroundPool `';
|
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value (
|
||||||
|
[string]::Format(
|
||||||
|
' -ThreadPool (Get-IcingaThreadPool -Name {0}MainPool{0}) `',
|
||||||
|
"'"
|
||||||
|
)
|
||||||
|
);
|
||||||
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value (
|
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value (
|
||||||
[string]::Format(
|
[string]::Format(
|
||||||
' -Command {0}{1}{0} `',
|
' -Command {0}{1}{0} `',
|
||||||
|
|
@ -157,7 +159,7 @@ function New-IcingaForWindowsComponent()
|
||||||
);
|
);
|
||||||
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value (
|
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value (
|
||||||
[string]::Format(
|
[string]::Format(
|
||||||
' -CmdParameters @{{ {0}IcingaDaemonData{0} = $global:IcingaDaemonData }} `',
|
' -CmdParameters @{{ }} `',
|
||||||
"'"
|
"'"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
@ -166,9 +168,6 @@ function New-IcingaForWindowsComponent()
|
||||||
|
|
||||||
Set-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ([string]::Format('function {0}()', $DaemonEntry));
|
Set-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ([string]::Format('function {0}()', $DaemonEntry));
|
||||||
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value '{';
|
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value '{';
|
||||||
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' param (';
|
|
||||||
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' $IcingaDaemonData';
|
|
||||||
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' );';
|
|
||||||
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value '';
|
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value '';
|
||||||
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' # This is your main daemon function. Add your code inside the WHILE() loop which is executed once the daemon is loaded.';
|
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' # This is your main daemon function. Add your code inside the WHILE() loop which is executed once the daemon is loaded.';
|
||||||
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' # Also check the developer guide for further details: https://icinga.com/docs/icinga-for-windows/latest/doc/900-Developer-Guide/10-Custom-Daemons/';
|
Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' # Also check the developer guide for further details: https://icinga.com/docs/icinga-for-windows/latest/doc/900-Developer-Guide/10-Custom-Daemons/';
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,5 @@
|
||||||
|
|
||||||
function Clear-IcingaCheckSchedulerCheckData()
|
function Clear-IcingaCheckSchedulerCheckData()
|
||||||
{
|
{
|
||||||
if ($null -eq $global:Icinga) {
|
$global:Icinga.Private.Scheduler.CheckData.Clear();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($global:Icinga.ContainsKey('CheckData') -eq $FALSE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$global:Icinga.CheckData.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,18 @@
|
||||||
|
|
||||||
function Clear-IcingaCheckSchedulerEnvironment()
|
function Clear-IcingaCheckSchedulerEnvironment()
|
||||||
{
|
{
|
||||||
if ($null -eq $global:Icinga) {
|
param (
|
||||||
return;
|
[switch]$ClearCheckData = $FALSE
|
||||||
}
|
);
|
||||||
|
|
||||||
Get-IcingaCheckSchedulerPluginOutput | Out-Null;
|
Get-IcingaCheckSchedulerPluginOutput | Out-Null;
|
||||||
Get-IcingaCheckSchedulerPerfData | Out-Null;
|
Get-IcingaCheckSchedulerPerfData | Out-Null;
|
||||||
Clear-IcingaCheckSchedulerCheckData;
|
|
||||||
|
if ($ClearCheckData) {
|
||||||
|
Clear-IcingaCheckSchedulerCheckData;
|
||||||
|
}
|
||||||
|
|
||||||
|
$Global:Icinga.Private.Scheduler.PluginException = $null;
|
||||||
|
$Global:Icinga.Private.Scheduler.CheckResults = $null;
|
||||||
|
$Global:Icinga.Private.Scheduler.ExitCode = $null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Disables the debug mode of the Framework
|
Disables the debug mode of the Framework
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Disables the debug mode of the Framework
|
Disables the debug mode of the Framework
|
||||||
.FUNCTIONALITY
|
.FUNCTIONALITY
|
||||||
Disables the Icinga for Windows Debug-Log
|
Disables the Icinga for Windows Debug-Log
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
PS>Disable-IcingaFrameworkDebugMode;
|
PS>Disable-IcingaFrameworkDebugMode;
|
||||||
.LINK
|
.LINK
|
||||||
https://github.com/Icinga/icinga-powershell-framework
|
https://github.com/Icinga/icinga-powershell-framework
|
||||||
#>
|
#>
|
||||||
|
|
||||||
function Disable-IcingaFrameworkDebugMode()
|
function Disable-IcingaFrameworkDebugMode()
|
||||||
{
|
{
|
||||||
$global:IcingaDaemonData.DebugMode = $FALSE;
|
$Global:Icinga.Protected.DebugMode = $FALSE;
|
||||||
Set-IcingaPowerShellConfig -Path 'Framework.DebugMode' -Value $FALSE;
|
Set-IcingaPowerShellConfig -Path 'Framework.DebugMode' -Value $FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Enables the debug mode of the Framework to print additional details into
|
Enables the debug mode of the Framework to print additional details into
|
||||||
the Windows Event Log with Id 1000
|
the Windows Event Log with Id 1000
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Enables the debug mode of the Framework to print additional details into
|
Enables the debug mode of the Framework to print additional details into
|
||||||
the Windows Event Log with Id 1000
|
the Windows Event Log with Id 1000
|
||||||
.FUNCTIONALITY
|
.FUNCTIONALITY
|
||||||
Enables the Icinga for Windows Debug-Log
|
Enables the Icinga for Windows Debug-Log
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
PS>Enable-IcingaFrameworkDebugMode;
|
PS>Enable-IcingaFrameworkDebugMode;
|
||||||
.LINK
|
.LINK
|
||||||
https://github.com/Icinga/icinga-powershell-framework
|
https://github.com/Icinga/icinga-powershell-framework
|
||||||
#>
|
#>
|
||||||
|
|
||||||
function Enable-IcingaFrameworkDebugMode()
|
function Enable-IcingaFrameworkDebugMode()
|
||||||
{
|
{
|
||||||
$global:IcingaDaemonData.DebugMode = $TRUE;
|
$Global:Icinga.Protected.DebugMode = $TRUE;
|
||||||
Set-IcingaPowerShellConfig -Path 'Framework.DebugMode' -Value $TRUE;
|
Set-IcingaPowerShellConfig -Path 'Framework.DebugMode' -Value $TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,5 @@
|
||||||
|
|
||||||
function Get-IcingaCheckSchedulerCheckData()
|
function Get-IcingaCheckSchedulerCheckData()
|
||||||
{
|
{
|
||||||
if ($null -eq $global:Icinga) {
|
return $global:Icinga.Private.Scheduler.CheckData;
|
||||||
return $null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($global:Icinga.ContainsKey('CheckData') -eq $FALSE) {
|
|
||||||
return @{ };
|
|
||||||
}
|
|
||||||
|
|
||||||
return $global:Icinga.CheckData;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,24 @@
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Function to fetch the last executed plugin peformance data
|
Function to fetch the last executed plugin performance data
|
||||||
from an internal memory cache in case the Framework is running as daemon.
|
from an internal memory cache in case the Framework is running as daemon.
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
While running the Framework as daemon, checkresults for plugins are not
|
While running the Framework as daemon, check results for plugins are not
|
||||||
printed into the console but written into an internal memory cache. Once
|
printed into the console but written into an internal memory cache. Once
|
||||||
a plugin was executed, use this function to fetch the plugin performance data
|
a plugin was executed, use this function to fetch the plugin performance data
|
||||||
.FUNCTIONALITY
|
.FUNCTIONALITY
|
||||||
Returns the last performance data output for executed plugins while the
|
Returns the last performance data output for executed plugins while the
|
||||||
Framework is running as daemon
|
Framework is running as daemon
|
||||||
.OUTPUTS
|
.OUTPUTS
|
||||||
System.Object
|
System.Object
|
||||||
.LINK
|
.LINK
|
||||||
https://github.com/Icinga/icinga-powershell-framework
|
https://github.com/Icinga/icinga-powershell-framework
|
||||||
#>
|
#>
|
||||||
|
|
||||||
function Get-IcingaCheckSchedulerPerfData()
|
function Get-IcingaCheckSchedulerPerfData()
|
||||||
{
|
{
|
||||||
if ($null -eq $global:Icinga) {
|
$PerfData = $Global:Icinga.Private.Scheduler.PerformanceData;
|
||||||
return $null;
|
$Global:Icinga.Private.Scheduler.PerformanceData = @();
|
||||||
}
|
|
||||||
|
|
||||||
$PerfData = $global:Icinga.PerfData;
|
|
||||||
$global:Icinga.PerfData = @();
|
|
||||||
|
|
||||||
return $PerfData;
|
return $PerfData;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,8 @@
|
||||||
|
|
||||||
function Get-IcingaCheckSchedulerPluginOutput()
|
function Get-IcingaCheckSchedulerPluginOutput()
|
||||||
{
|
{
|
||||||
if ($null -eq $global:Icinga) {
|
$CheckResult = [string]::Join("`r`n", $Global:Icinga.Private.Scheduler.CheckResults);
|
||||||
return $null;
|
$Global:Icinga.Private.Scheduler.CheckResults = @();
|
||||||
}
|
|
||||||
|
|
||||||
$CheckResult = [string]::Join("`r`n", $global:Icinga.CheckResults);
|
|
||||||
$global:Icinga.CheckResults = @();
|
|
||||||
|
|
||||||
return $CheckResult;
|
return $CheckResult;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,6 @@ function Get-IcingaPrivateEnvironmentVariable()
|
||||||
return $null;
|
return $null;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Setup the environments in case not present already
|
|
||||||
New-IcingaEnvironmentVariable;
|
|
||||||
|
|
||||||
if ($global:Icinga.Private.ContainsKey($Name) -eq $FALSE) {
|
if ($global:Icinga.Private.ContainsKey($Name) -eq $FALSE) {
|
||||||
return $null;
|
return $null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ function Get-IcingaTimer()
|
||||||
[string]$Name = 'DefaultTimer'
|
[string]$Name = 'DefaultTimer'
|
||||||
);
|
);
|
||||||
|
|
||||||
$TimerData = Get-IcingaHashtableItem -Key $Name -Hashtable $global:IcingaDaemonData.IcingaTimers;
|
$TimerData = Get-IcingaHashtableItem -Key $Name -Hashtable $Global:Icinga.Private.Timers;
|
||||||
|
|
||||||
if ($null -eq $TimerData) {
|
if ($null -eq $TimerData) {
|
||||||
return $null;
|
return $null;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ function Invoke-IcingaInternalServiceCall()
|
||||||
);
|
);
|
||||||
|
|
||||||
# If our Framework is running as daemon, never call our api
|
# If our Framework is running as daemon, never call our api
|
||||||
if ($global:IcingaDaemonData.FrameworkRunningAsDaemon) {
|
if ($Global:Icinga.Protected.RunAsDaemon) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,10 +83,8 @@ function Invoke-IcingaInternalServiceCall()
|
||||||
try {
|
try {
|
||||||
$ApiResult = Invoke-WebRequest -Method POST -UseBasicParsing -Uri ([string]::Format('https://localhost:{0}/v1/checker?command={1}', $RestApiPort, $Command)) -Body (ConvertTo-JsonUTF8Bytes -InputObject $CommandArguments -Depth 100 -Compress) -ContentType 'application/json' -TimeoutSec $Timeout;
|
$ApiResult = Invoke-WebRequest -Method POST -UseBasicParsing -Uri ([string]::Format('https://localhost:{0}/v1/checker?command={1}', $RestApiPort, $Command)) -Body (ConvertTo-JsonUTF8Bytes -InputObject $CommandArguments -Depth 100 -Compress) -ContentType 'application/json' -TimeoutSec $Timeout;
|
||||||
} catch {
|
} catch {
|
||||||
# Something went wrong -> fallback to local execution
|
|
||||||
$ExMsg = $_.Exception.message;
|
|
||||||
# Fallback to execute plugin locally
|
# Fallback to execute plugin locally
|
||||||
Write-IcingaEventMessage -Namespace 'Framework' -EventId 1553 -Objects $ExMsg, $Command, $CommandArguments;
|
Write-IcingaEventMessage -Namespace 'Framework' -EventId 1553 -ExceptionObject $_ -Objects $Command, $CommandArguments;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ function Invoke-IcingaNamespaceCmdlets()
|
||||||
-Key $Cmdlet.Name `
|
-Key $Cmdlet.Name `
|
||||||
-Value $Content | Out-Null;
|
-Value $Content | Out-Null;
|
||||||
} catch {
|
} catch {
|
||||||
Write-IcingaEventMessage -EventId 1103 -Namespace 'Framework' -Objects $CommandName, $_.Exception.Message;
|
Write-IcingaEventMessage -EventId 1103 -Namespace 'Framework' -ExceptionObject $_ -Objects $CommandName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Create a new environment in which we can store check results, performance data
|
|
||||||
and values over time or executed plugins.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
Access the string plugin output by calling `Get-IcingaCheckSchedulerPluginOutput`
|
|
||||||
Access possible performance data with `Get-IcingaCheckSchedulerPerfData`
|
|
||||||
|
|
||||||
If you execute check plugins, ensure you read both of these functions to fetch the
|
|
||||||
result of the plugin call and to clear the stack and memory of the check data.
|
|
||||||
|
|
||||||
If you do not require the output, you can write them to Null
|
|
||||||
|
|
||||||
Get-IcingaCheckSchedulerPluginOutput | Out-Null;
|
|
||||||
Get-IcingaCheckSchedulerPerfData | Out-Null;
|
|
||||||
|
|
||||||
IMPORTANT:
|
|
||||||
In addition each value for each object created with `New-IcingaCheck` is stored
|
|
||||||
with a timestamp for the check command inside a hashtable. If you do not require
|
|
||||||
these data, you MUST call `Clear-IcingaCheckSchedulerCheckData` to free memory
|
|
||||||
and clear data from the stack!
|
|
||||||
|
|
||||||
If you are finished with all data processing and do not require anything within
|
|
||||||
memory anyway, you can safely call `Clear-IcingaCheckSchedulerEnvironment` to
|
|
||||||
do the same thing in one call.
|
|
||||||
.DESCRIPTION
|
|
||||||
Fetch the raw output values for a check command for each single object
|
|
||||||
processed by New-IcingaCheck
|
|
||||||
.FUNCTIONALITY
|
|
||||||
Fetch the raw output values for a check command for each single object
|
|
||||||
processed by New-IcingaCheck
|
|
||||||
.OUTPUTS
|
|
||||||
System.Object
|
|
||||||
.LINK
|
|
||||||
https://github.com/Icinga/icinga-powershell-framework
|
|
||||||
#>
|
|
||||||
|
|
||||||
function New-IcingaCheckSchedulerEnvironment()
|
|
||||||
{
|
|
||||||
# Legacy code
|
|
||||||
if ($IcingaDaemonData.IcingaThreadContent.ContainsKey('Scheduler') -eq $FALSE) {
|
|
||||||
$IcingaDaemonData.IcingaThreadContent.Add('Scheduler', @{ });
|
|
||||||
}
|
|
||||||
|
|
||||||
New-IcingaEnvironmentVariable;
|
|
||||||
}
|
|
||||||
|
|
@ -11,27 +11,52 @@
|
||||||
|
|
||||||
function New-IcingaEnvironmentVariable()
|
function New-IcingaEnvironmentVariable()
|
||||||
{
|
{
|
||||||
if ($null -eq $global:Icinga) {
|
if ($null -eq $Global:Icinga) {
|
||||||
$global:Icinga = @{ };
|
$Global:Icinga = @{ };
|
||||||
}
|
}
|
||||||
|
|
||||||
# Session specific configuration for this shell
|
# Session specific configuration for this shell
|
||||||
if ($global:Icinga.ContainsKey('Private') -eq $FALSE) {
|
if ($Global:Icinga.ContainsKey('Private') -eq $FALSE) {
|
||||||
$global:Icinga.Add('Private', @{ });
|
$Global:Icinga.Add('Private', @{ });
|
||||||
|
|
||||||
|
$Global:Icinga.Private.Add('Daemons', @{ });
|
||||||
|
$Global:Icinga.Private.Add('Timers', @{ });
|
||||||
|
|
||||||
|
$Global:Icinga.Private.Add(
|
||||||
|
'Scheduler',
|
||||||
|
@{
|
||||||
|
'CheckData' = @{ };
|
||||||
|
'ThresholdCache' = @{ };
|
||||||
|
'CheckResults' = @();
|
||||||
|
'PerformanceData' = @();
|
||||||
|
'PluginException' = $null;
|
||||||
|
'ExitCode' = $null;
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Shared configuration for all threads
|
# Shared configuration for all threads
|
||||||
if ($global:Icinga.ContainsKey('Public') -eq $FALSE) {
|
if ($Global:Icinga.ContainsKey('Public') -eq $FALSE) {
|
||||||
$global:Icinga.Add('Public', [hashtable]::Synchronized(@{ }));
|
$Global:Icinga.Add('Public', [hashtable]::Synchronized(@{ }));
|
||||||
|
|
||||||
|
$Global:Icinga.Public.Add('Daemons', @{ });
|
||||||
|
$Global:Icinga.Public.Add('Threads', @{ });
|
||||||
|
$Global:Icinga.Public.Add('ThreadPools', @{ });
|
||||||
|
$Global:Icinga.Public.Add(
|
||||||
|
'PerformanceCounter',
|
||||||
|
@{
|
||||||
|
'Cache' = @{ };
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($global:Icinga.ContainsKey('CheckResults') -eq $FALSE) {
|
# Session specific configuration which should never be modified by users!
|
||||||
$global:Icinga.Add('CheckResults', @());
|
if ($Global:Icinga.ContainsKey('Protected') -eq $FALSE) {
|
||||||
}
|
$Global:Icinga.Add('Protected', @{ });
|
||||||
if ($global:Icinga.ContainsKey('PerfData') -eq $FALSE) {
|
|
||||||
$global:Icinga.Add('PerfData', @());
|
$Global:Icinga.Protected.Add('DebugMode', $FALSE);
|
||||||
}
|
$Global:Icinga.Protected.Add('JEAContext', $FALSE);
|
||||||
if ($global:Icinga.ContainsKey('CheckData') -eq $FALSE) {
|
$Global:Icinga.Protected.Add('RunAsDaemon', $FALSE);
|
||||||
$global:Icinga.Add('CheckData', @{ });
|
$Global:Icinga.Protected.Add('Minimal', $FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,6 @@ function Set-IcingaPrivateEnvironmentVariable()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Setup the environments in case not present already
|
|
||||||
New-IcingaEnvironmentVariable;
|
|
||||||
|
|
||||||
if ($global:Icinga.Private.ContainsKey($Name) -eq $FALSE) {
|
if ($global:Icinga.Private.ContainsKey($Name) -eq $FALSE) {
|
||||||
$global:Icinga.Private.Add($Name, $Value);
|
$global:Icinga.Private.Add($Name, $Value);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Returns the spent time since Start-IcingaTimer was executed in seconds for
|
Returns the spent time since Start-IcingaTimer was executed in seconds for
|
||||||
a specific timer name
|
a specific timer name
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Returns the spent time since Start-IcingaTimer was executed in seconds for
|
Returns the spent time since Start-IcingaTimer was executed in seconds for
|
||||||
a specific timer name
|
a specific timer name
|
||||||
.FUNCTIONALITY
|
.FUNCTIONALITY
|
||||||
Returns the spent time since Start-IcingaTimer was executed in seconds for
|
Returns the spent time since Start-IcingaTimer was executed in seconds for
|
||||||
a specific timer name
|
a specific timer name
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
PS>Show-IcingaTimer;
|
PS>Show-IcingaTimer;
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
PS>Show-IcingaTimer -Name 'My Test Timer';
|
PS>Show-IcingaTimer -Name 'My Test Timer';
|
||||||
.PARAMETER Name
|
.PARAMETER Name
|
||||||
The name of a custom identifier to run mutliple timers at once
|
The name of a custom identifier to run multiple timers at once
|
||||||
.INPUTS
|
.INPUTS
|
||||||
System.String
|
System.String
|
||||||
.OUTPUTS
|
.OUTPUTS
|
||||||
Single
|
Single
|
||||||
.LINK
|
.LINK
|
||||||
https://github.com/Icinga/icinga-powershell-framework
|
https://github.com/Icinga/icinga-powershell-framework
|
||||||
#>
|
#>
|
||||||
|
|
||||||
function Show-IcingaTimer()
|
function Show-IcingaTimer()
|
||||||
|
|
@ -32,8 +32,8 @@ function Show-IcingaTimer()
|
||||||
$TimerObject = Get-IcingaTimer -Name $Name;
|
$TimerObject = Get-IcingaTimer -Name $Name;
|
||||||
|
|
||||||
if (-Not $ShowAll) {
|
if (-Not $ShowAll) {
|
||||||
if ($null -eq $TimerObject) {
|
if ($null -eq $TimerObject) {
|
||||||
Write-IcingaConsoleNotice 'A timer with the name "{0}" does not exist' -Objects $Name;
|
Write-IcingaConsoleNotice 'A timer with the name "{0}" does not exist' -Objects $Name;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,17 +43,17 @@ function Show-IcingaTimer()
|
||||||
|
|
||||||
$TimerOutput | Format-Table -AutoSize;
|
$TimerOutput | Format-Table -AutoSize;
|
||||||
} else {
|
} else {
|
||||||
$TimerObjects = Get-IcingaHashtableItem -Key 'IcingaTimers' -Hashtable $global:IcingaDaemonData;
|
$TimerObjects = Get-IcingaHashtableItem -Key 'Timers' -Hashtable $Global:Icinga.Private;
|
||||||
|
|
||||||
[array]$MultiOutput = @();
|
[array]$MultiOutput = @();
|
||||||
|
|
||||||
foreach ($TimerName in $TimerObjects.Keys) {
|
foreach ($TimerName in $TimerObjects.Keys) {
|
||||||
$TimerObject = $TimerObjects[$TimerName].Timer;
|
$TimerObject = $TimerObjects[$TimerName].Timer;
|
||||||
|
|
||||||
$TimerOutput = New-Object -TypeName PSObject;
|
$TimerOutput = New-Object -TypeName PSObject;
|
||||||
$TimerOutput | Add-Member -MemberType NoteProperty -Name 'Timer Name' -Value $TimerName;
|
$TimerOutput | Add-Member -MemberType NoteProperty -Name 'Timer Name' -Value $TimerName;
|
||||||
$TimerOutput | Add-Member -MemberType NoteProperty -Name 'Elapsed Seconds' -Value $TimerObject.Elapsed.TotalSeconds;
|
$TimerOutput | Add-Member -MemberType NoteProperty -Name 'Elapsed Seconds' -Value $TimerObject.Elapsed.TotalSeconds;
|
||||||
$MultiOutput += $TimerOutput;
|
$MultiOutput += $TimerOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
$MultiOutput | Format-Table -AutoSize;
|
$MultiOutput | Format-Table -AutoSize;
|
||||||
|
|
|
||||||
|
|
@ -37,11 +37,9 @@ function Start-IcingaTimer()
|
||||||
$TimerObject.Start();
|
$TimerObject.Start();
|
||||||
|
|
||||||
Add-IcingaHashtableItem -Key $Name -Value (
|
Add-IcingaHashtableItem -Key $Name -Value (
|
||||||
[hashtable]::Synchronized(
|
@{
|
||||||
@{
|
'Active' = $TRUE;
|
||||||
'Active' = $TRUE;
|
'Timer' = $TimerObject;
|
||||||
'Timer' = $TimerObject;
|
}
|
||||||
}
|
) -Hashtable $Global:Icinga.Private.Timers -Override | Out-Null;
|
||||||
)
|
|
||||||
) -Hashtable $global:IcingaDaemonData.IcingaTimers -Override | Out-Null;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,9 @@ function Stop-IcingaTimer()
|
||||||
$TimerObject.Stop();
|
$TimerObject.Stop();
|
||||||
}
|
}
|
||||||
Add-IcingaHashtableItem -Key $Name -Value (
|
Add-IcingaHashtableItem -Key $Name -Value (
|
||||||
[hashtable]::Synchronized(
|
@{
|
||||||
@{
|
'Active' = $FALSE;
|
||||||
'Active' = $FALSE;
|
'Timer' = $TimerObject;
|
||||||
'Timer' = $TimerObject;
|
}
|
||||||
}
|
) -Hashtable $Global:Icinga.Private.Timers -Override | Out-Null;
|
||||||
)
|
|
||||||
) -Hashtable $global:IcingaDaemonData.IcingaTimers -Override | Out-Null;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Tests if a specific timer object is already present and started with Start-IcingaTimer
|
Tests if a specific timer object is already present and started with Start-IcingaTimer
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Tests if a specific timer object is already present and started with Start-IcingaTimer
|
Tests if a specific timer object is already present and started with Start-IcingaTimer
|
||||||
.FUNCTIONALITY
|
.FUNCTIONALITY
|
||||||
Tests if a specific timer object is already present and started with Start-IcingaTimer
|
Tests if a specific timer object is already present and started with Start-IcingaTimer
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
PS>Test-IcingaTimer;
|
PS>Test-IcingaTimer;
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
PS>Test-IcingaTimer -Name 'My Test Timer';
|
PS>Test-IcingaTimer -Name 'My Test Timer';
|
||||||
.PARAMETER Name
|
.PARAMETER Name
|
||||||
The name of a custom identifier to run mutliple timers at once
|
The name of a custom identifier to run mutliple timers at once
|
||||||
.INPUTS
|
.INPUTS
|
||||||
System.String
|
System.String
|
||||||
.OUTPUTS
|
.OUTPUTS
|
||||||
Boolean
|
Boolean
|
||||||
.LINK
|
.LINK
|
||||||
https://github.com/Icinga/icinga-powershell-framework
|
https://github.com/Icinga/icinga-powershell-framework
|
||||||
#>
|
#>
|
||||||
|
|
||||||
function Test-IcingaTimer()
|
function Test-IcingaTimer()
|
||||||
|
|
@ -25,7 +25,7 @@ function Test-IcingaTimer()
|
||||||
[string]$Name = 'DefaultTimer'
|
[string]$Name = 'DefaultTimer'
|
||||||
);
|
);
|
||||||
|
|
||||||
$TimerData = Get-IcingaHashtableItem -Key $Name -Hashtable $global:IcingaDaemonData.IcingaTimers;
|
$TimerData = Get-IcingaHashtableItem -Key $Name -Hashtable $Global:Icinga.Private.Timers;
|
||||||
|
|
||||||
if ($null -eq $TimerData) {
|
if ($null -eq $TimerData) {
|
||||||
return $FALSE;
|
return $FALSE;
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ function Get-IcingaJEAConfiguration()
|
||||||
-CmdName 'Exit-IcingaExecutePlugin' `
|
-CmdName 'Exit-IcingaExecutePlugin' `
|
||||||
-CmdType 'Function';
|
-CmdType 'Function';
|
||||||
|
|
||||||
# We need to add this function for our background daemon we start with 'Start-IcingaPowerShellDaemon',
|
# We need to add this function for our background daemon we start with 'Start-IcingaForWindowsDaemon',
|
||||||
# as this function is called outside the JEA context
|
# as this function is called outside the JEA context
|
||||||
$UsedCmdlets = Get-IcingaCommandDependency `
|
$UsedCmdlets = Get-IcingaCommandDependency `
|
||||||
-DependencyList $DependencyList `
|
-DependencyList $DependencyList `
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,30 @@ if ($null -eq $IcingaEventLogEnums -Or $IcingaEventLogEnums.ContainsKey('Framewo
|
||||||
'Details' = 'Icinga for Windows could not find the Function or Cmdlet for the specified background daemon. The daemon was not loaded.';
|
'Details' = 'Icinga for Windows could not find the Function or Cmdlet for the specified background daemon. The daemon was not loaded.';
|
||||||
'EventId' = 1400;
|
'EventId' = 1400;
|
||||||
};
|
};
|
||||||
|
1401 = @{
|
||||||
|
'EntryType' = 'Error';
|
||||||
|
'Message' = 'Icinga for Windows thread pool not found';
|
||||||
|
'Details' = 'Icinga for Windows was unable to find a specified thread pool with [Get-IcingaThreadPool] for a background daemon. To keep the daemon running, it defaulted to a basic pool but this issue should be addressed. The name of the inquired pool is:';
|
||||||
|
'EventId' = 1401;
|
||||||
|
};
|
||||||
|
1450 = @{
|
||||||
|
'EntryType' = 'Error';
|
||||||
|
'Message' = 'Icinga for Windows service check daemon invalid index';
|
||||||
|
'Details' = 'Icinga for Windows is unable to process the provided time index for a background service check task, as a given index is not numeric';
|
||||||
|
'EventId' = 1450;
|
||||||
|
};
|
||||||
|
1451 = @{
|
||||||
|
'EntryType' = 'Error';
|
||||||
|
'Message' = 'Icinga for Windows service check daemon exception on plugin execution';
|
||||||
|
'Details' = 'Icinga for Windows failed to execute a plugin within the background service check daemon with an exception';
|
||||||
|
'EventId' = 1451;
|
||||||
|
};
|
||||||
|
1452 = @{
|
||||||
|
'EntryType' = 'Error';
|
||||||
|
'Message' = 'Icinga for Windows service check daemon failed with exception';
|
||||||
|
'Details' = 'Icinga for Windows failed to properly execute a task within the background service check daemon with a given exception';
|
||||||
|
'EventId' = 1452;
|
||||||
|
};
|
||||||
1500 = @{
|
1500 = @{
|
||||||
'EntryType' = 'Error';
|
'EntryType' = 'Error';
|
||||||
'Message' = 'Failed to securely establish a communication between this server and the client';
|
'Message' = 'Failed to securely establish a communication between this server and the client';
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ function Write-IcingaConsoleOutput()
|
||||||
}
|
}
|
||||||
|
|
||||||
# Never write console output in case the Framework is running as daemon
|
# Never write console output in case the Framework is running as daemon
|
||||||
if ($null -ne $global:IcingaDaemonData -And $null -ne $global:IcingaDaemonData.FrameworkRunningAsDaemon -And $global:IcingaDaemonData.FrameworkRunningAsDaemon -eq $TRUE) {
|
if ($Global:Icinga.Protected.RunAsDaemon -eq $TRUE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ function Write-IcingaDebugMessage()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($null -eq $global:IcingaDaemonData -Or $global:IcingaDaemonData.DebugMode -eq $FALSE) {
|
if ($Global:Icinga.Protected.DebugMode -eq $FALSE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,10 @@ function Add-IcingaPerformanceCounterCache()
|
||||||
$Instances
|
$Instances
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($global:Icinga_PerfCounterCache.ContainsKey($Counter)) {
|
if ($Global:Icinga.Public.PerformanceCounter.Cache.ContainsKey($Counter)) {
|
||||||
$global:Icinga_PerfCounterCache[$Counter] = $Instances;
|
$Global:Icinga.Public.PerformanceCounter.Cache[$Counter] = $Instances;
|
||||||
} else {
|
} else {
|
||||||
$global:Icinga_PerfCounterCache.Add(
|
$Global:Icinga.Public.PerformanceCounter.Cache.Add(
|
||||||
$Counter, $Instances
|
$Counter, $Instances
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ function Get-IcingaPerformanceCounterCacheItem()
|
||||||
$Counter
|
$Counter
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($global:Icinga_PerfCounterCache.ContainsKey($Counter)) {
|
if ($Global:Icinga.Public.PerformanceCounter.Cache.ContainsKey($Counter)) {
|
||||||
return $global:Icinga_PerfCounterCache[$Counter];
|
return $Global:Icinga.Public.PerformanceCounter.Cache[$Counter];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $null;
|
return $null;
|
||||||
|
|
|
||||||
|
|
@ -55,9 +55,8 @@ function New-IcingaPerformanceCounterArray()
|
||||||
# TODO: Add a cache for our Performance Counters to only fetch them once
|
# TODO: Add a cache for our Performance Counters to only fetch them once
|
||||||
# for each session to speed up the loading. This cold be something like
|
# for each session to speed up the loading. This cold be something like
|
||||||
# this:
|
# this:
|
||||||
# New-IcingaPerformanceCounterCache $CounterResult;
|
#
|
||||||
# Internally we could do something like this
|
# $Global:Icinga.Public.PerformanceCounter.Cache += $CounterResult;
|
||||||
# $global:Icinga_PerfCounterCache += $CounterResult;
|
|
||||||
|
|
||||||
# Above we initialise ever single counter and we only require a sleep once
|
# Above we initialise ever single counter and we only require a sleep once
|
||||||
# in case a new, yet unknown counter was added
|
# in case a new, yet unknown counter was added
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Initialises the internal cache storage for Performance Counters
|
|
||||||
.DESCRIPTION
|
|
||||||
Initialises the internal cache storage for Performance Counters
|
|
||||||
.FUNCTIONALITY
|
|
||||||
Initialises the internal cache storage for Performance Counters
|
|
||||||
.EXAMPLE
|
|
||||||
PS>New-IcingaPerformanceCounterCache;
|
|
||||||
.LINK
|
|
||||||
https://github.com/Icinga/icinga-powershell-framework
|
|
||||||
#>
|
|
||||||
|
|
||||||
function New-IcingaPerformanceCounterCache()
|
|
||||||
{
|
|
||||||
if ($null -eq $global:Icinga_PerfCounterCache) {
|
|
||||||
$global:Icinga_PerfCounterCache = (
|
|
||||||
[hashtable]::Synchronized(
|
|
||||||
@{ }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
17
lib/core/thread/Add-IcingaThreadPool.psm1
Normal file
17
lib/core/thread/Add-IcingaThreadPool.psm1
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
function Add-IcingaThreadPool()
|
||||||
|
{
|
||||||
|
param (
|
||||||
|
[string]$Name = '',
|
||||||
|
[int]$MinInstances = 1,
|
||||||
|
[int]$MaxInstances = 5
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($Global:Icinga.Public.ThreadPools.ContainsKey($Name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$Global:Icinga.Public.ThreadPools.Add(
|
||||||
|
$Name,
|
||||||
|
(New-IcingaThreadPool -MinInstances $MinInstances -MaxInstances $MaxInstances)
|
||||||
|
);
|
||||||
|
}
|
||||||
14
lib/core/thread/Get-IcingaThreadPool.psm1
Normal file
14
lib/core/thread/Get-IcingaThreadPool.psm1
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
function Get-IcingaThreadPool()
|
||||||
|
{
|
||||||
|
param (
|
||||||
|
[string]$Name
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($Global:Icinga.Public.ThreadPools.ContainsKey($Name)) {
|
||||||
|
return $Global:Icinga.Public.ThreadPools[$Name];
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-IcingaEventMessage -Namespace 'Framework' -EventId 1401 -Objects $Name;
|
||||||
|
|
||||||
|
return (New-IcingaThreadPool);
|
||||||
|
}
|
||||||
|
|
@ -10,14 +10,19 @@ function New-IcingaThreadInstance()
|
||||||
[Switch]$Start
|
[Switch]$Start
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$CallStack = Get-PSCallStack;
|
||||||
|
$SourceCommand = $CallStack[1].Command;
|
||||||
|
|
||||||
if ([string]::IsNullOrEmpty($Name)) {
|
if ([string]::IsNullOrEmpty($Name)) {
|
||||||
$Name = New-IcingaThreadHash -ShellScript $ScriptBlock -Arguments $Arguments;
|
$Name = New-IcingaThreadHash -ShellScript $ScriptBlock -Arguments $Arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$ThreadName = [string]::Format('{0}::{1}::{2}::0', $SourceCommand, $Command, $Name);
|
||||||
|
|
||||||
Write-IcingaDebugMessage -Message (
|
Write-IcingaDebugMessage -Message (
|
||||||
[string]::Format(
|
[string]::Format(
|
||||||
'Creating new thread instance {0}{1}Arguments:{1}{2}',
|
'Creating new thread instance {0}{1}Arguments:{1}{2}',
|
||||||
$Name,
|
$ThreadName,
|
||||||
"`r`n",
|
"`r`n",
|
||||||
($Arguments | Out-String)
|
($Arguments | Out-String)
|
||||||
)
|
)
|
||||||
|
|
@ -29,10 +34,17 @@ function New-IcingaThreadInstance()
|
||||||
|
|
||||||
if ([string]::IsNullOrEmpty($Command) -eq $FALSE) {
|
if ([string]::IsNullOrEmpty($Command) -eq $FALSE) {
|
||||||
|
|
||||||
|
# Initialize the Icinga for Windows environment in each thread
|
||||||
[void]$Shell.AddCommand('Use-Icinga');
|
[void]$Shell.AddCommand('Use-Icinga');
|
||||||
[void]$Shell.AddParameter('-LibOnly', $TRUE);
|
[void]$Shell.AddParameter('-LibOnly', $TRUE);
|
||||||
[void]$Shell.AddParameter('-Daemon', $TRUE);
|
[void]$Shell.AddParameter('-Daemon', $TRUE);
|
||||||
|
|
||||||
|
# Share our public data between all threads
|
||||||
|
if ($null -ne $Global:Icinga -And $Global:Icinga.ContainsKey('Public')) {
|
||||||
|
[void]$Shell.AddCommand('Set-IcingaEnvironmentGlobal');
|
||||||
|
[void]$Shell.AddParameter('GlobalEnvironment', $Global:Icinga.Public);
|
||||||
|
}
|
||||||
|
|
||||||
[void]$Shell.AddCommand($Command);
|
[void]$Shell.AddCommand($Command);
|
||||||
|
|
||||||
$CodeHash = $Command;
|
$CodeHash = $Command;
|
||||||
|
|
@ -76,12 +88,16 @@ function New-IcingaThreadInstance()
|
||||||
Add-Member -InputObject $Thread -MemberType NoteProperty -Name Started -Value $FALSE;
|
Add-Member -InputObject $Thread -MemberType NoteProperty -Name Started -Value $FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($global:IcingaDaemonData.IcingaThreads.ContainsKey($Name) -eq $FALSE) {
|
[int]$ThreadIndex = 0;
|
||||||
$global:IcingaDaemonData.IcingaThreads.Add($Name, $Thread);
|
|
||||||
} else {
|
while ($TRUE) {
|
||||||
$global:IcingaDaemonData.IcingaThreads.Add(
|
|
||||||
(New-IcingaThreadHash -ShellScript $CodeHash -Arguments $Arguments),
|
if ($Global:Icinga.Public.Threads.ContainsKey($ThreadName) -eq $FALSE) {
|
||||||
$Thread
|
$Global:Icinga.Public.Threads.Add($ThreadName, $Thread);
|
||||||
);
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ThreadIndex += 1;
|
||||||
|
$ThreadName = [string]::Format('{0}::{1}::{2}::{3}', $SourceCommand, $Command, $Name, $ThreadIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,10 @@ function Remove-IcingaThread()
|
||||||
|
|
||||||
Stop-IcingaThread -Thread $Thread;
|
Stop-IcingaThread -Thread $Thread;
|
||||||
|
|
||||||
if ($global:IcingaDaemonData.IcingaThreads.ContainsKey($Thread)) {
|
if ($Global:Icinga.Public.Threads.ContainsKey($Thread)) {
|
||||||
$global:IcingaDaemonData.IcingaThreads[$Thread].Shell.Dispose();
|
$Global:Icinga.Public.Threads[$Thread].Shell.Dispose();
|
||||||
$global:IcingaDaemonData.IcingaThreads.Remove($Thread);
|
$Global:Icinga.Public.Threads.Remove($Thread);
|
||||||
|
|
||||||
|
Write-IcingaDebugMessage 'Removing Thread: {0}' -Objects $Thread;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
lib/core/thread/Set-IcingaEnvironmentGlobal.psm1
Normal file
16
lib/core/thread/Set-IcingaEnvironmentGlobal.psm1
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
function Set-IcingaEnvironmentGlobal()
|
||||||
|
{
|
||||||
|
param (
|
||||||
|
$GlobalEnvironment = $null
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($null -eq $GlobalEnvironment -Or $null -eq $Global:Icinga) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Global:Icinga.ContainsKey('Public') -eq $FALSE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$Global:Icinga.Public = $GlobalEnvironment;
|
||||||
|
}
|
||||||
|
|
@ -8,10 +8,10 @@ function Start-IcingaThread()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($global:IcingaDaemonData.IcingaThreads.ContainsKey($Thread)) {
|
if ($Global:Icinga.Public.Threads.ContainsKey($Thread)) {
|
||||||
if ($global:IcingaDaemonData.IcingaThreads[$Thread].Started -eq $FALSE) {
|
if ($Global:Icinga.Public.Threads[$Thread].Started -eq $FALSE) {
|
||||||
$global:IcingaDaemonData.IcingaThreads[$Thread].Handle = $global:IcingaDaemonData.IcingaThreads[$Thread].Shell.BeginInvoke();
|
$Global:Icinga.Public.Threads[$Thread].Handle = $Global:Icinga.Public.Threads[$Thread].Shell.BeginInvoke();
|
||||||
$global:IcingaDaemonData.IcingaThreads[$Thread].Started = $TRUE;
|
$Global:Icinga.Public.Threads[$Thread].Started = $TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,11 @@ function Stop-IcingaThread()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($global:IcingaDaemonData.IcingaThreads.ContainsKey($Thread)) {
|
if ($Global:Icinga.Public.Threads.ContainsKey($Thread)) {
|
||||||
if ($global:IcingaDaemonData.IcingaThreads[$Thread].Started -eq $TRUE) {
|
if ($Global:Icinga.Public.Threads[$Thread].Started -eq $TRUE) {
|
||||||
$global:IcingaDaemonData.IcingaThreads[$Thread].Shell.Stop();
|
$Global:Icinga.Public.Threads[$Thread].Shell.Stop();
|
||||||
$global:IcingaDaemonData.IcingaThreads[$Thread].Handle = $null;
|
$Global:Icinga.Public.Threads[$Thread].Handle = $null;
|
||||||
$global:IcingaDaemonData.IcingaThreads[$Thread].Started = $FALSE;
|
$Global:Icinga.Public.Threads[$Thread].Started = $FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,5 @@ function Test-IcingaThread()
|
||||||
return $FALSE;
|
return $FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $global:IcingaDaemonData.IcingaThreads.ContainsKey($Thread);
|
return $Global:Icinga.Public.Threads.ContainsKey($Thread);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,5 @@
|
||||||
function Add-IcingaForWindowsDaemon()
|
function Add-IcingaForWindowsDaemon()
|
||||||
{
|
{
|
||||||
param (
|
|
||||||
$IcingaDaemonData
|
|
||||||
);
|
|
||||||
|
|
||||||
Use-Icinga -LibOnly -Daemon;
|
|
||||||
$Global:IcingaDaemonData = $IcingaDaemonData;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$EnabledDaemons = Get-IcingaBackgroundDaemons;
|
$EnabledDaemons = Get-IcingaBackgroundDaemons;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,17 @@ function Start-IcingaPowerShellDaemon()
|
||||||
[switch]$JEARestart = $FALSE
|
[switch]$JEARestart = $FALSE
|
||||||
);
|
);
|
||||||
|
|
||||||
$global:IcingaDaemonData.FrameworkRunningAsDaemon = $TRUE;
|
Start-IcingaForWindowsDaemon -RunAsService:$RunAsService -JEARestart:$JEARestart;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Start-IcingaForWindowsDaemon()
|
||||||
|
{
|
||||||
|
param (
|
||||||
|
[switch]$RunAsService = $FALSE,
|
||||||
|
[switch]$JEARestart = $FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
$Global:Icinga.Protected.RunAsDaemon = $TRUE;
|
||||||
[string]$MainServicePidFile = (Join-Path -Path (Get-IcingaCacheDir) -ChildPath 'service.pid');
|
[string]$MainServicePidFile = (Join-Path -Path (Get-IcingaCacheDir) -ChildPath 'service.pid');
|
||||||
[string]$JeaPidFile = (Join-Path -Path (Get-IcingaCacheDir) -ChildPath 'jea.pid');
|
[string]$JeaPidFile = (Join-Path -Path (Get-IcingaCacheDir) -ChildPath 'jea.pid');
|
||||||
[string]$JeaProfile = Get-IcingaPowerShellConfig -Path 'Framework.JEAProfile';
|
[string]$JeaProfile = Get-IcingaPowerShellConfig -Path 'Framework.JEAProfile';
|
||||||
|
|
@ -23,13 +32,13 @@ function Start-IcingaPowerShellDaemon()
|
||||||
if ([string]::IsNullOrEmpty($JeaProfile)) {
|
if ([string]::IsNullOrEmpty($JeaProfile)) {
|
||||||
Write-IcingaDebugMessage -Message 'Starting Icinga for Windows service without JEA context' -Objects $RunAsService, $JEARestart, $JeaProfile;
|
Write-IcingaDebugMessage -Message 'Starting Icinga for Windows service without JEA context' -Objects $RunAsService, $JEARestart, $JeaProfile;
|
||||||
|
|
||||||
$global:IcingaDaemonData.FrameworkRunningAsDaemon = $TRUE;
|
$Global:Icinga.Protected.RunAsDaemon = $TRUE;
|
||||||
$global:IcingaDaemonData.Add('BackgroundDaemon', [hashtable]::Synchronized(@{ }));
|
|
||||||
# Todo: Add config for active background tasks. Set it to 20 for the moment
|
# Todo: Add config for active background tasks. Set it to 20 for the moment
|
||||||
$global:IcingaDaemonData.IcingaThreadPool.Add('BackgroundPool', (New-IcingaThreadPool -MaxInstances 20));
|
Add-IcingaThreadPool -Name 'MainPool' -MaxInstances 20;
|
||||||
$global:IcingaDaemonData.Add('SSLCertificate', $Certificate);
|
$Global:Icinga.Public.Add('SSLCertificate', $Certificate);
|
||||||
|
|
||||||
New-IcingaThreadInstance -Name "Icinga_PowerShell_Background_Daemon" -ThreadPool $IcingaDaemonData.IcingaThreadPool.BackgroundPool -Command 'Add-IcingaForWindowsDaemon' -CmdParameters @{ 'IcingaDaemonData' = $global:IcingaDaemonData } -Start;
|
|
||||||
|
New-IcingaThreadInstance -Name "Main" -ThreadPool (Get-IcingaThreadPool -Name 'MainPool') -Command 'Add-IcingaForWindowsDaemon' -Start;
|
||||||
} else {
|
} else {
|
||||||
Write-IcingaDebugMessage -Message 'Starting Icinga for Windows service inside JEA context' -Objects $RunAsService, $JEARestart, $JeaProfile;
|
Write-IcingaDebugMessage -Message 'Starting Icinga for Windows service inside JEA context' -Objects $RunAsService, $JEARestart, $JeaProfile;
|
||||||
& powershell.exe -NoProfile -NoLogo -ConfigurationName $JeaProfile -Command {
|
& powershell.exe -NoProfile -NoLogo -ConfigurationName $JeaProfile -Command {
|
||||||
|
|
@ -38,24 +47,19 @@ function Start-IcingaPowerShellDaemon()
|
||||||
|
|
||||||
Write-IcingaFileSecure -File ($args[1]) -Value $PID;
|
Write-IcingaFileSecure -File ($args[1]) -Value $PID;
|
||||||
|
|
||||||
$Global:IcingaDaemonData.JEAContext = $TRUE;
|
$Global:Icinga.Protected.JEAContext = $TRUE;
|
||||||
$global:IcingaDaemonData.FrameworkRunningAsDaemon = $TRUE;
|
$Global:Icinga.Protected.RunAsDaemon = $TRUE;
|
||||||
$global:IcingaDaemonData.Add('BackgroundDaemon', [hashtable]::Synchronized(@{ }));
|
|
||||||
# Todo: Add config for active background tasks. Set it to 20 for the moment
|
# Todo: Add config for active background tasks. Set it to 20 for the moment
|
||||||
$global:IcingaDaemonData.IcingaThreadPool.Add('BackgroundPool', (New-IcingaThreadPool -MaxInstances 20));
|
Add-IcingaThreadPool -Name 'MainPool' -MaxInstances 20;
|
||||||
$global:IcingaDaemonData.Add('SSLCertificate', ($args[0]));
|
$Global:Icinga.Public.Add('SSLCertificate', $args[0]);
|
||||||
|
|
||||||
New-IcingaThreadInstance -Name "Icinga_PowerShell_Background_Daemon" -ThreadPool $IcingaDaemonData.IcingaThreadPool.BackgroundPool -Command 'Add-IcingaForWindowsDaemon' -CmdParameters @{ 'IcingaDaemonData' = $global:IcingaDaemonData } -Start;
|
New-IcingaThreadInstance -Name "Main" -ThreadPool (Get-IcingaThreadPool -Name 'MainPool') -Command 'Add-IcingaForWindowsDaemon' -Start;
|
||||||
|
|
||||||
while ($TRUE) {
|
while ($TRUE) {
|
||||||
Start-Sleep -Seconds 100;
|
Start-Sleep -Seconds 100;
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
$CallStack = @();
|
Write-IcingaEventMessage -EventId 1600 -Namespace 'Framework' -ExceptionObject $_;
|
||||||
foreach ($entry in (Get-PSCallStack)) {
|
|
||||||
$CallStack += [string]::Format('{0} => Line {1}', $entry.FunctionName, $entry.ScriptLineNumber);
|
|
||||||
}
|
|
||||||
Write-IcingaEventMessage -EventId 1600 -Namespace Framework -Objects $_.Exception.Message, $_.Exception.StackTrace, $CallStack;
|
|
||||||
}
|
}
|
||||||
} -Args $Certificate, $JeaPidFile;
|
} -Args $Certificate, $JeaPidFile;
|
||||||
}
|
}
|
||||||
|
|
@ -80,7 +84,7 @@ function Start-IcingaPowerShellDaemon()
|
||||||
|
|
||||||
Write-IcingaFileSecure -File $JeaPidFile -Value '';
|
Write-IcingaFileSecure -File $JeaPidFile -Value '';
|
||||||
Write-IcingaEventMessage -EventId 1505 -Namespace Framework -Objects ([string]::Format('{0}/5', $JeaRestartCounter));
|
Write-IcingaEventMessage -EventId 1505 -Namespace Framework -Objects ([string]::Format('{0}/5', $JeaRestartCounter));
|
||||||
Start-IcingaPowerShellDaemon -RunAsService:$RunAsService -JEARestart;
|
Start-IcingaForWindowsDaemon -RunAsService:$RunAsService -JEARestart;
|
||||||
|
|
||||||
$JeaRestartCounter += 1;
|
$JeaRestartCounter += 1;
|
||||||
$JeaPid = '';
|
$JeaPid = '';
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,6 @@ function Invoke-IcingaRESTAPIv1Calls()
|
||||||
);
|
);
|
||||||
|
|
||||||
[string]$ModuleToLoad = Get-IcingaRESTPathElement -Request $Request -Index 1;
|
[string]$ModuleToLoad = Get-IcingaRESTPathElement -Request $Request -Index 1;
|
||||||
# Map our Icinga globals to a shorter variable
|
|
||||||
$RestDaemon = $IcingaDaemonData.BackgroundDaemon.IcingaPowerShellRestApi;
|
|
||||||
|
|
||||||
if ([string]::IsNullOrEmpty($ModuleToLoad)) {
|
if ([string]::IsNullOrEmpty($ModuleToLoad)) {
|
||||||
Send-IcingaTCPClientMessage -Message (
|
Send-IcingaTCPClientMessage -Message (
|
||||||
|
|
@ -15,14 +13,14 @@ function Invoke-IcingaRESTAPIv1Calls()
|
||||||
-HTTPResponse ($IcingaHTTPEnums.HTTPResponseType.Ok) `
|
-HTTPResponse ($IcingaHTTPEnums.HTTPResponseType.Ok) `
|
||||||
-ContentBody @{
|
-ContentBody @{
|
||||||
'Endpoints' = @(
|
'Endpoints' = @(
|
||||||
$RestDaemon.RegisteredEndpoints.Keys
|
$Global:Icinga.Public.Daemons.RESTApi.RegisteredEndpoints.Keys
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) -Stream $Connection.Stream;
|
) -Stream $Connection.Stream;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($RestDaemon.RegisteredEndpoints.ContainsKey($ModuleToLoad) -eq $FALSE) {
|
if ($Global:Icinga.Public.Daemons.RESTApi.RegisteredEndpoints.ContainsKey($ModuleToLoad) -eq $FALSE) {
|
||||||
Send-IcingaTCPClientMessage -Message (
|
Send-IcingaTCPClientMessage -Message (
|
||||||
New-IcingaTCPClientRESTMessage `
|
New-IcingaTCPClientRESTMessage `
|
||||||
-HTTPResponse ($IcingaHTTPEnums.HTTPResponseType.'Not Found') `
|
-HTTPResponse ($IcingaHTTPEnums.HTTPResponseType.'Not Found') `
|
||||||
|
|
@ -31,7 +29,7 @@ function Invoke-IcingaRESTAPIv1Calls()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[string]$Command = $RestDaemon.RegisteredEndpoints[$ModuleToLoad];
|
[string]$Command = $Global:Icinga.Public.Daemons.RESTApi.RegisteredEndpoints[$ModuleToLoad];
|
||||||
|
|
||||||
Write-IcingaDebugMessage -Message 'Executing REST-Module' -Objects $Command;
|
Write-IcingaDebugMessage -Message 'Executing REST-Module' -Objects $Command;
|
||||||
|
|
||||||
|
|
@ -47,7 +45,6 @@ function Invoke-IcingaRESTAPIv1Calls()
|
||||||
[hashtable]$CommandArguments = @{
|
[hashtable]$CommandArguments = @{
|
||||||
'-Request' = $Request;
|
'-Request' = $Request;
|
||||||
'-Connection' = $Connection;
|
'-Connection' = $Connection;
|
||||||
'-IcingaGlobals' = $IcingaDaemonData;
|
|
||||||
'-ApiVersion' = 'v1';
|
'-ApiVersion' = 'v1';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ function Test-IcingaRESTClientConnection()
|
||||||
if ($null -eq $Connection.Stream) {
|
if ($null -eq $Connection.Stream) {
|
||||||
Add-IcingaRESTClientBlacklistCount `
|
Add-IcingaRESTClientBlacklistCount `
|
||||||
-Client $Connection.Client `
|
-Client $Connection.Client `
|
||||||
-ClientList $IcingaDaemonData.BackgroundDaemon.IcingaPowerShellRestApi.ClientBlacklist;
|
-ClientList $Global:Icinga.Public.Daemons.RESTApi.ClientBlacklist;
|
||||||
Write-IcingaEventMessage -EventId 1501 -Namespace 'Framework' -Objects $Connection.Client.Client;
|
Write-IcingaEventMessage -EventId 1501 -Namespace 'Framework' -Objects $Connection.Client.Client;
|
||||||
Close-IcingaTCPConnection -Client $Connection.Client;
|
Close-IcingaTCPConnection -Client $Connection.Client;
|
||||||
$Connection = $null;
|
$Connection = $null;
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,8 @@ function New-IcingaForWindowsRESTApi()
|
||||||
{
|
{
|
||||||
# Allow us to parse the framework global data to this thread
|
# Allow us to parse the framework global data to this thread
|
||||||
param (
|
param (
|
||||||
$IcingaDaemonData,
|
|
||||||
[string]$Address = '',
|
[string]$Address = '',
|
||||||
$Port,
|
$Port,
|
||||||
$RootFolder,
|
|
||||||
$CertFile,
|
$CertFile,
|
||||||
$CertThumbprint,
|
$CertThumbprint,
|
||||||
$RequireAuth
|
$RequireAuth
|
||||||
|
|
@ -15,49 +13,6 @@ function New-IcingaForWindowsRESTApi()
|
||||||
# as daemon
|
# as daemon
|
||||||
Use-Icinga -LibOnly -Daemon;
|
Use-Icinga -LibOnly -Daemon;
|
||||||
|
|
||||||
$Global:IcingaDaemonData = $IcingaDaemonData;
|
|
||||||
|
|
||||||
# Add a synchronized hashtable to the global data background
|
|
||||||
# daemon hashtable to write data to. In addition it will
|
|
||||||
# allow to share data collected from this daemon with others
|
|
||||||
$IcingaDaemonData.BackgroundDaemon.Add(
|
|
||||||
'IcingaPowerShellRestApi',
|
|
||||||
[hashtable]::Synchronized(@{ })
|
|
||||||
);
|
|
||||||
|
|
||||||
# Map our Icinga globals to a shorter variable
|
|
||||||
$RestDaemon = $IcingaDaemonData.BackgroundDaemon.IcingaPowerShellRestApi;
|
|
||||||
|
|
||||||
# This will add another hashtable to our previous
|
|
||||||
# IcingaPowerShellRestApi hashtable to store actual
|
|
||||||
# endpoint configurations for the API
|
|
||||||
$RestDaemon.Add(
|
|
||||||
'RegisteredEndpoints',
|
|
||||||
[hashtable]::Synchronized(@{ })
|
|
||||||
);
|
|
||||||
|
|
||||||
# This will add another hashtable to our previous
|
|
||||||
# IcingaPowerShellRestApi hashtable to store actual
|
|
||||||
# command aliases for execution for the API
|
|
||||||
$RestDaemon.Add(
|
|
||||||
'CommandAliases',
|
|
||||||
[hashtable]::Synchronized(@{ })
|
|
||||||
);
|
|
||||||
|
|
||||||
# This will add another hashtable to our previous
|
|
||||||
# IcingaPowerShellRestApi hashtable to store actual
|
|
||||||
# command aliases for execution for the API
|
|
||||||
$RestDaemon.Add(
|
|
||||||
'ClientBlacklist',
|
|
||||||
[hashtable]::Synchronized(@{ })
|
|
||||||
);
|
|
||||||
|
|
||||||
# Make the root folder of our rest daemon module available
|
|
||||||
# for every possible thread we require
|
|
||||||
$RestDaemon.Add(
|
|
||||||
'RootFolder', $RootFolder
|
|
||||||
);
|
|
||||||
|
|
||||||
$RESTEndpoints = Invoke-IcingaNamespaceCmdlets -Command 'Register-IcingaRESTAPIEndpoint*';
|
$RESTEndpoints = Invoke-IcingaNamespaceCmdlets -Command 'Register-IcingaRESTAPIEndpoint*';
|
||||||
Write-IcingaDebugMessage -Message (
|
Write-IcingaDebugMessage -Message (
|
||||||
[string]::Format(
|
[string]::Format(
|
||||||
|
|
@ -67,12 +22,13 @@ function New-IcingaForWindowsRESTApi()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
Write-IcingaDebugMessage -Message ($RestDaemon | Out-String);
|
Write-IcingaDebugMessage -Message ($Global:Icinga.Public.Daemons.RESTApi | Out-String);
|
||||||
|
|
||||||
foreach ($entry in $RESTEndpoints.Values) {
|
foreach ($entry in $RESTEndpoints.Values) {
|
||||||
[bool]$Success = Add-IcingaHashtableItem -Hashtable $RestDaemon.RegisteredEndpoints `
|
[bool]$Success = Add-IcingaHashtableItem `
|
||||||
-Key $entry.Alias `
|
-Hashtable $Global:Icinga.Public.Daemons.RESTApi.RegisteredEndpoints `
|
||||||
-Value $entry.Command;
|
-Key $entry.Alias `
|
||||||
|
-Value $entry.Command;
|
||||||
|
|
||||||
if ($Success -eq $FALSE) {
|
if ($Success -eq $FALSE) {
|
||||||
Write-IcingaEventMessage `
|
Write-IcingaEventMessage `
|
||||||
|
|
@ -86,9 +42,10 @@ function New-IcingaForWindowsRESTApi()
|
||||||
|
|
||||||
foreach ($entry in $CommandAliases.Values) {
|
foreach ($entry in $CommandAliases.Values) {
|
||||||
foreach ($component in $entry.Keys) {
|
foreach ($component in $entry.Keys) {
|
||||||
[bool]$Success = Add-IcingaHashtableItem -Hashtable $RestDaemon.CommandAliases `
|
[bool]$Success = Add-IcingaHashtableItem `
|
||||||
-Key $component `
|
-Hashtable $Global:Icinga.Public.Daemons.RESTApi.CommandAliases `
|
||||||
-Value $entry[$component];
|
-Key $component `
|
||||||
|
-Value $entry[$component];
|
||||||
|
|
||||||
if ($Success -eq $FALSE) {
|
if ($Success -eq $FALSE) {
|
||||||
Write-IcingaEventMessage `
|
Write-IcingaEventMessage `
|
||||||
|
|
@ -99,15 +56,15 @@ function New-IcingaForWindowsRESTApi()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-IcingaDebugMessage -Message ($RestDaemon.RegisteredEndpoints | Out-String);
|
Write-IcingaDebugMessage -Message ($Global:Icinga.Public.Daemons.RESTApi.RegisteredEndpoints | Out-String);
|
||||||
|
|
||||||
if ($Global:IcingaDaemonData.JEAContext) {
|
if ($Global:Icinga.Protected.JEAContext) {
|
||||||
if ($global:IcingaDaemonData.ContainsKey('SSLCertificate') -eq $FALSE -Or $null -eq $global:IcingaDaemonData.SSLCertificate) {
|
if ($Global:Icinga.Public.ContainsKey('SSLCertificate') -eq $FALSE -Or $null -eq $Global:Icinga.Public.SSLCertificate) {
|
||||||
Write-IcingaEventMessage -EventId 2001 -Namespace 'RESTApi';
|
Write-IcingaEventMessage -EventId 2001 -Namespace 'RESTApi';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$Certificate = $global:IcingaDaemonData.SSLCertificate;
|
$Certificate = $Global:Icinga.Public.SSLCertificate;
|
||||||
} else {
|
} else {
|
||||||
$Certificate = Get-IcingaSSLCertForSocket -CertFile $CertFile -CertThumbprint $CertThumbprint;
|
$Certificate = Get-IcingaSSLCertForSocket -CertFile $CertFile -CertThumbprint $CertThumbprint;
|
||||||
}
|
}
|
||||||
|
|
@ -131,7 +88,7 @@ function New-IcingaForWindowsRESTApi()
|
||||||
-Client (New-IcingaTCPClient -Socket $Socket) `
|
-Client (New-IcingaTCPClient -Socket $Socket) `
|
||||||
-Certificate $Certificate;
|
-Certificate $Certificate;
|
||||||
|
|
||||||
if (Test-IcingaRESTClientBlacklisted -Client $Connection.Client -ClientList $RestDaemon.ClientBlacklist) {
|
if (Test-IcingaRESTClientBlacklisted -Client $Connection.Client -ClientList $Global:Icinga.Public.Daemons.RESTApi.ClientBlacklist) {
|
||||||
Write-IcingaDebugMessage -Message 'A remote client which is trying to connect was blacklisted' -Objects $Connection.Client.Client;
|
Write-IcingaDebugMessage -Message 'A remote client which is trying to connect was blacklisted' -Objects $Connection.Client.Client;
|
||||||
Close-IcingaTCPConnection -Client $Connection.Client;
|
Close-IcingaTCPConnection -Client $Connection.Client;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -142,7 +99,7 @@ function New-IcingaForWindowsRESTApi()
|
||||||
}
|
}
|
||||||
|
|
||||||
# API not yet ready
|
# API not yet ready
|
||||||
if ($IcingaDaemonData.IcingaThreadContent.RESTApi.ApiRequests.Count -eq 0) {
|
if ($Global:Icinga.Public.Daemons.RESTApi.ApiRequests.Count -eq 0) {
|
||||||
Close-IcingaTCPConnection -Client $Connection.Client;
|
Close-IcingaTCPConnection -Client $Connection.Client;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -150,15 +107,14 @@ function New-IcingaForWindowsRESTApi()
|
||||||
try {
|
try {
|
||||||
$NextRESTApiThreadId = (Get-IcingaNextRESTApiThreadId);
|
$NextRESTApiThreadId = (Get-IcingaNextRESTApiThreadId);
|
||||||
|
|
||||||
if ($IcingaDaemonData.IcingaThreadContent.RESTApi.ApiRequests.ContainsKey($NextRESTApiThreadId) -eq $FALSE) {
|
if ($Global:Icinga.Public.Daemons.RESTApi.ApiRequests.ContainsKey($NextRESTApiThreadId) -eq $FALSE) {
|
||||||
Close-IcingaTCPConnection -Client $Connection.Client;
|
Close-IcingaTCPConnection -Client $Connection.Client;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$IcingaDaemonData.IcingaThreadContent.RESTApi.ApiRequests.$NextRESTApiThreadId.Enqueue($Connection);
|
$Global:Icinga.Public.Daemons.RESTApi.ApiRequests.$NextRESTApiThreadId.Enqueue($Connection);
|
||||||
} catch {
|
} catch {
|
||||||
$ExMsg = $_.Exception.Message;
|
Write-IcingaEventMessage -Namespace 'RESTApi' -EvenId 2050 -ExceptionObject $_;
|
||||||
Write-IcingaEventMessage -Namespace 'RESTApi' -EvenId 2050 -Objects $ExMsg;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,29 +54,20 @@ function Start-IcingaWindowsRESTApi()
|
||||||
[int]$Timeout = 30
|
[int]$Timeout = 30
|
||||||
);
|
);
|
||||||
|
|
||||||
$RootFolder = $PSScriptRoot;
|
New-IcingaForWindowsRESTEnvironment -ThreadCount $ConcurrentThreads;
|
||||||
|
|
||||||
$global:IcingaDaemonData.IcingaThreadContent.Add('RESTApi', ([hashtable]::Synchronized(@{ })));
|
|
||||||
$global:IcingaDaemonData.IcingaThreadPool.Add('IcingaRESTApi', (New-IcingaThreadPool -MaxInstances ($ThreadId + 3)));
|
|
||||||
$global:IcingaDaemonData.IcingaThreadContent.RESTApi.Add('ApiRequests', ([hashtable]::Synchronized(@{ })));
|
|
||||||
$global:IcingaDaemonData.IcingaThreadContent.RESTApi.Add('ApiCallThreadAssignment', ([hashtable]::Synchronized(@{ })));
|
|
||||||
$global:IcingaDaemonData.IcingaThreadContent.RESTApi.Add('TotalThreads', $ConcurrentThreads);
|
|
||||||
$global:IcingaDaemonData.IcingaThreadContent.RESTApi.Add('LastThreadId', 0);
|
|
||||||
|
|
||||||
# Now create a new thread for our REST-Api, assign a name and parse all required arguments to it.
|
# Now create a new thread for our REST-Api, assign a name and parse all required arguments to it.
|
||||||
# Last but not least start it directly
|
# Last but not least start it directly
|
||||||
New-IcingaThreadInstance `
|
New-IcingaThreadInstance `
|
||||||
-Name 'Icinga_for_Windows_REST_Api' `
|
-Name 'Main' `
|
||||||
-ThreadPool $global:IcingaDaemonData.IcingaThreadPool.IcingaRESTApi `
|
-ThreadPool (Get-IcingaThreadPool -Name 'RESTApiPool') `
|
||||||
-Command 'New-IcingaForWindowsRESTApi' `
|
-Command 'New-IcingaForWindowsRESTApi' `
|
||||||
-CmdParameters @{
|
-CmdParameters @{
|
||||||
'IcingaDaemonData' = $global:IcingaDaemonData;
|
'Address' = $Address;
|
||||||
'Address' = $Address;
|
'Port' = $Port;
|
||||||
'Port' = $Port;
|
'CertFile' = $CertFile;
|
||||||
'RootFolder' = $RootFolder;
|
'CertThumbprint' = $CertThumbprint;
|
||||||
'CertFile' = $CertFile;
|
'RequireAuth' = $RequireAuth;
|
||||||
'CertThumbprint' = $CertThumbprint;
|
|
||||||
'RequireAuth' = $RequireAuth;
|
|
||||||
} `
|
} `
|
||||||
-Start;
|
-Start;
|
||||||
|
|
||||||
|
|
@ -85,7 +76,7 @@ function Start-IcingaWindowsRESTApi()
|
||||||
while ($ConcurrentThreads -gt 0) {
|
while ($ConcurrentThreads -gt 0) {
|
||||||
$ConcurrentThreads = $ConcurrentThreads - 1;
|
$ConcurrentThreads = $ConcurrentThreads - 1;
|
||||||
[System.Collections.Queue]$RESTThreadQueue = @();
|
[System.Collections.Queue]$RESTThreadQueue = @();
|
||||||
$global:IcingaDaemonData.IcingaThreadContent.RESTApi.ApiRequests.Add($ThreadId, [System.Collections.Queue]::Synchronized($RESTThreadQueue));
|
$Global:Icinga.Public.Daemons.RESTApi.ApiRequests.Add($ThreadId, [System.Collections.Queue]::Synchronized($RESTThreadQueue));
|
||||||
Start-IcingaForWindowsRESTThread -ThreadId $ThreadId -RequireAuth:$RequireAuth;
|
Start-IcingaForWindowsRESTThread -ThreadId $ThreadId -RequireAuth:$RequireAuth;
|
||||||
$ThreadId += 1;
|
$ThreadId += 1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
function Get-IcingaNextRESTApiThreadId()
|
function Get-IcingaNextRESTApiThreadId()
|
||||||
{
|
{
|
||||||
[int]$ConcurrentThreads = $IcingaDaemonData.IcingaThreadContent.RESTApi.TotalThreads - 1;
|
[int]$ConcurrentThreads = $Global:Icinga.Public.Daemons.RESTApi.TotalThreads - 1;
|
||||||
[int]$LastThreadId = $IcingaDaemonData.IcingaThreadContent.RESTApi.LastThreadId + 1;
|
[int]$LastThreadId = $Global:Icinga.Public.Daemons.RESTApi.LastThreadId + 1;
|
||||||
|
|
||||||
if ($LastThreadId -gt $ConcurrentThreads) {
|
if ($LastThreadId -gt $ConcurrentThreads) {
|
||||||
$LastThreadId = 0;
|
$LastThreadId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$IcingaDaemonData.IcingaThreadContent.RESTApi.LastThreadId = $LastThreadId;
|
$Global:Icinga.Public.Daemons.RESTApi.LastThreadId = $LastThreadId;
|
||||||
|
|
||||||
return $LastThreadId;
|
return $LastThreadId;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
function New-IcingaForWindowsRESTThread()
|
function New-IcingaForWindowsRESTThread()
|
||||||
{
|
{
|
||||||
param(
|
param(
|
||||||
$IcingaDaemonData,
|
|
||||||
$RequireAuth,
|
$RequireAuth,
|
||||||
$ThreadId
|
$ThreadId
|
||||||
);
|
);
|
||||||
|
|
@ -9,7 +8,6 @@ function New-IcingaForWindowsRESTThread()
|
||||||
# Import the framework library components and initialise it
|
# Import the framework library components and initialise it
|
||||||
# as daemon
|
# as daemon
|
||||||
Use-Icinga -LibOnly -Daemon;
|
Use-Icinga -LibOnly -Daemon;
|
||||||
$Global:IcingaDaemonData = $IcingaDaemonData;
|
|
||||||
|
|
||||||
# Initialise our performance counter categories
|
# Initialise our performance counter categories
|
||||||
Show-IcingaPerformanceCounterCategories | Out-Null;
|
Show-IcingaPerformanceCounterCategories | Out-Null;
|
||||||
|
|
@ -17,17 +15,17 @@ function New-IcingaForWindowsRESTThread()
|
||||||
while ($TRUE) {
|
while ($TRUE) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($IcingaDaemonData.IcingaThreadContent.RESTApi.ApiRequests.ContainsKey($ThreadId) -eq $FALSE) {
|
if ($Global:Icinga.Public.Daemons.RESTApi.ApiRequests.ContainsKey($ThreadId) -eq $FALSE) {
|
||||||
Start-Sleep -Milliseconds 10;
|
Start-Sleep -Milliseconds 10;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($IcingaDaemonData.IcingaThreadContent.RESTApi.ApiRequests.$ThreadId.Count -eq 0) {
|
if ($Global:Icinga.Public.Daemons.RESTApi.ApiRequests.$ThreadId.Count -eq 0) {
|
||||||
Start-Sleep -Milliseconds 10;
|
Start-Sleep -Milliseconds 10;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$Connection = $IcingaDaemonData.IcingaThreadContent.RESTApi.ApiRequests.$ThreadId.Dequeue();
|
$Connection = $Global:Icinga.Public.Daemons.RESTApi.ApiRequests.$ThreadId.Dequeue();
|
||||||
|
|
||||||
if ($null -eq $Connection) {
|
if ($null -eq $Connection) {
|
||||||
Start-Sleep -Milliseconds 10;
|
Start-Sleep -Milliseconds 10;
|
||||||
|
|
@ -49,7 +47,7 @@ function New-IcingaForWindowsRESTThread()
|
||||||
# to ensure we are not spammed and "attacked" by a client with useless requests
|
# to ensure we are not spammed and "attacked" by a client with useless requests
|
||||||
Add-IcingaRESTClientBlacklistCount `
|
Add-IcingaRESTClientBlacklistCount `
|
||||||
-Client $Connection.Client `
|
-Client $Connection.Client `
|
||||||
-ClientList $IcingaDaemonData.BackgroundDaemon.IcingaPowerShellRestApi.ClientBlacklist;
|
-ClientList $Global:Icinga.Public.Daemons.RESTApi.ClientBlacklist;
|
||||||
# Send the authentication prompt
|
# Send the authentication prompt
|
||||||
Send-IcingaWebAuthMessage -Connection $Connection;
|
Send-IcingaWebAuthMessage -Connection $Connection;
|
||||||
# Close the connection
|
# Close the connection
|
||||||
|
|
@ -66,7 +64,7 @@ function New-IcingaForWindowsRESTThread()
|
||||||
# Failed attempts should increase the blacklist counter
|
# Failed attempts should increase the blacklist counter
|
||||||
Add-IcingaRESTClientBlacklistCount `
|
Add-IcingaRESTClientBlacklistCount `
|
||||||
-Client $Connection.Client `
|
-Client $Connection.Client `
|
||||||
-ClientList $IcingaDaemonData.BackgroundDaemon.IcingaPowerShellRestApi.ClientBlacklist;
|
-ClientList $Global:Icinga.Public.Daemons.RESTApi.ClientBlacklist;
|
||||||
# Re-send the authentication prompt
|
# Re-send the authentication prompt
|
||||||
Send-IcingaWebAuthMessage -Connection $Connection;
|
Send-IcingaWebAuthMessage -Connection $Connection;
|
||||||
# Close the connection
|
# Close the connection
|
||||||
|
|
@ -76,7 +74,7 @@ function New-IcingaForWindowsRESTThread()
|
||||||
}
|
}
|
||||||
|
|
||||||
# We should remove clients from the blacklist who are sending valid requests
|
# We should remove clients from the blacklist who are sending valid requests
|
||||||
Remove-IcingaRESTClientBlacklist -Client $Connection.Client -ClientList $IcingaDaemonData.BackgroundDaemon.IcingaPowerShellRestApi.ClientBlacklist;
|
Remove-IcingaRESTClientBlacklist -Client $Connection.Client -ClientList $Global:Icinga.Public.Daemons.RESTApi.ClientBlacklist;
|
||||||
switch (Get-IcingaRESTPathElement -Request $RESTRequest -Index 0) {
|
switch (Get-IcingaRESTPathElement -Request $RESTRequest -Index 0) {
|
||||||
'v1' {
|
'v1' {
|
||||||
Invoke-IcingaRESTAPIv1Calls -Request $RESTRequest -Connection $Connection;
|
Invoke-IcingaRESTAPIv1Calls -Request $RESTRequest -Connection $Connection;
|
||||||
|
|
@ -101,7 +99,7 @@ function New-IcingaForWindowsRESTThread()
|
||||||
-ContentBody $ExMsg
|
-ContentBody $ExMsg
|
||||||
) -Stream $Connection.Stream;
|
) -Stream $Connection.Stream;
|
||||||
|
|
||||||
Write-IcingaEventMessage -Namespace 'RESTApi' -EventId 2051 -Objects $ExMsg;
|
Write-IcingaEventMessage -Namespace 'RESTApi' -EventId 2051 -ExceptionObject $_;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Finally close the clients connection as we are done here and
|
# Finally close the clients connection as we are done here and
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,12 @@ function Start-IcingaForWindowsRESTThread()
|
||||||
# Now create a new thread, assign a name and parse all required arguments to it.
|
# Now create a new thread, assign a name and parse all required arguments to it.
|
||||||
# Last but not least start it directly
|
# Last but not least start it directly
|
||||||
New-IcingaThreadInstance `
|
New-IcingaThreadInstance `
|
||||||
-Name ([string]::Format("Icinga_Windows_REST_Api_Thread_{0}", $ThreadId)) `
|
-Name 'CheckThread' `
|
||||||
-ThreadPool (New-IcingaThreadPool -MaxInstances 1) `
|
-ThreadPool (New-IcingaThreadPool -MaxInstances 1) `
|
||||||
-Command 'New-IcingaForWindowsRESTThread' `
|
-Command 'New-IcingaForWindowsRESTThread' `
|
||||||
-CmdParameters @{
|
-CmdParameters @{
|
||||||
'IcingaDaemonData' = $global:IcingaDaemonData;
|
'RequireAuth' = $RequireAuth;
|
||||||
'RequireAuth' = $RequireAuth;
|
'ThreadId' = $ThreadId;
|
||||||
'ThreadId' = $ThreadId;
|
|
||||||
} `
|
} `
|
||||||
-Start;
|
-Start;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
function New-IcingaForWindowsRESTEnvironment()
|
||||||
|
{
|
||||||
|
param (
|
||||||
|
[int]$ThreadCount = 5
|
||||||
|
);
|
||||||
|
|
||||||
|
$Global:Icinga.Public.Daemons.Add(
|
||||||
|
'RESTApi',
|
||||||
|
@{
|
||||||
|
'ApiRequests' = @{ };
|
||||||
|
'ApiCallThreadAssignment' = @{ };
|
||||||
|
'TotalThreads' = $ThreadCount;
|
||||||
|
'LastThreadId' = 0;
|
||||||
|
# This will add another hashtable to our previous
|
||||||
|
# IcingaPowerShellRestApi hashtable to store actual
|
||||||
|
# endpoint configurations for the API
|
||||||
|
'RegisteredEndpoints' = @{ };
|
||||||
|
# This will add another hashtable to our previous
|
||||||
|
# IcingaPowerShellRestApi hashtable to store actual
|
||||||
|
# command aliases for execution for the API
|
||||||
|
'CommandAliases' = @{ };
|
||||||
|
# This will add another hashtable to our previous
|
||||||
|
# IcingaPowerShellRestApi hashtable to store actual
|
||||||
|
# command aliases for execution for the API
|
||||||
|
'ClientBlacklist' = @{ };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Add-IcingaThreadPool -Name 'RESTApiPool' -MaxInstances ($ThreadCount * 2);
|
||||||
|
}
|
||||||
|
|
@ -1,161 +0,0 @@
|
||||||
function Add-IcingaServiceCheckTask()
|
|
||||||
{
|
|
||||||
param (
|
|
||||||
$IcingaDaemonData,
|
|
||||||
$CheckCommand,
|
|
||||||
$Arguments,
|
|
||||||
$Interval,
|
|
||||||
$TimeIndexes,
|
|
||||||
$CheckId
|
|
||||||
);
|
|
||||||
|
|
||||||
Use-Icinga -LibOnly -Daemon;
|
|
||||||
|
|
||||||
$PassedTime = 0;
|
|
||||||
$SortedResult = $null;
|
|
||||||
$PerfCache = @{ };
|
|
||||||
$AverageCalc = @{ };
|
|
||||||
[int]$MaxTime = 0;
|
|
||||||
|
|
||||||
# Initialise some global variables we use to actually store check result data from
|
|
||||||
# plugins properly. This is doable from each thread instance as this part isn't
|
|
||||||
# shared between daemons
|
|
||||||
New-IcingaCheckSchedulerEnvironment;
|
|
||||||
|
|
||||||
foreach ($index in $TimeIndexes) {
|
|
||||||
# Only allow numeric index values
|
|
||||||
if ((Test-Numeric $index) -eq $FALSE) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($AverageCalc.ContainsKey([string]$index) -eq $FALSE) {
|
|
||||||
$AverageCalc.Add(
|
|
||||||
[string]$index,
|
|
||||||
@{
|
|
||||||
'Interval' = ([int]$index);
|
|
||||||
'Time' = ([int]$index * 60);
|
|
||||||
'Sum' = 0;
|
|
||||||
'Count' = 0;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ($MaxTime -le [int]$index) {
|
|
||||||
$MaxTime = [int]$index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[int]$MaxTimeInSeconds = $MaxTime * 60;
|
|
||||||
|
|
||||||
if (-Not ($global:Icinga.CheckData.ContainsKey($CheckCommand))) {
|
|
||||||
$global:Icinga.CheckData.Add($CheckCommand, @{ });
|
|
||||||
$global:Icinga.CheckData[$CheckCommand].Add('results', @{ });
|
|
||||||
$global:Icinga.CheckData[$CheckCommand].Add('average', @{ });
|
|
||||||
}
|
|
||||||
|
|
||||||
$LoadedCacheData = Get-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult_store' -KeyName $CheckCommand;
|
|
||||||
|
|
||||||
if ($null -ne $LoadedCacheData) {
|
|
||||||
foreach ($entry in $LoadedCacheData.PSObject.Properties) {
|
|
||||||
$global:Icinga.CheckData[$CheckCommand]['results'].Add(
|
|
||||||
$entry.name,
|
|
||||||
@{ }
|
|
||||||
);
|
|
||||||
foreach ($item in $entry.Value.PSObject.Properties) {
|
|
||||||
$global:Icinga.CheckData[$CheckCommand]['results'][$entry.name].Add(
|
|
||||||
$item.Name,
|
|
||||||
$item.Value
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while ($TRUE) {
|
|
||||||
if ($PassedTime -ge $Interval) {
|
|
||||||
try {
|
|
||||||
& $CheckCommand @Arguments | Out-Null;
|
|
||||||
} catch {
|
|
||||||
# Just for debugging. Not required in production or usable at all
|
|
||||||
$ErrMsg = $_.Exception.Message;
|
|
||||||
Write-IcingaConsoleError $ErrMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$UnixTime = Get-IcingaUnixTime;
|
|
||||||
|
|
||||||
foreach ($result in $global:Icinga.CheckData[$CheckCommand]['results'].Keys) {
|
|
||||||
[string]$HashIndex = $result;
|
|
||||||
$SortedResult = $global:Icinga.CheckData[$CheckCommand]['results'][$HashIndex].GetEnumerator() | Sort-Object name -Descending;
|
|
||||||
Add-IcingaHashtableItem -Hashtable $PerfCache -Key $HashIndex -Value @{ } | Out-Null;
|
|
||||||
|
|
||||||
foreach ($timeEntry in $SortedResult) {
|
|
||||||
|
|
||||||
if ((Test-Numeric $timeEntry.Value) -eq $FALSE) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($calc in $AverageCalc.Keys) {
|
|
||||||
if (($UnixTime - $AverageCalc[$calc].Time) -le [int]$timeEntry.Key) {
|
|
||||||
$AverageCalc[$calc].Sum += $timeEntry.Value;
|
|
||||||
$AverageCalc[$calc].Count += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (($UnixTime - $MaxTimeInSeconds) -le [int]$timeEntry.Key) {
|
|
||||||
Add-IcingaHashtableItem -Hashtable $PerfCache[$HashIndex] -Key ([string]$timeEntry.Key) -Value ([string]$timeEntry.Value) | Out-Null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($calc in $AverageCalc.Keys) {
|
|
||||||
if ($AverageCalc[$calc].Count -ne 0) {
|
|
||||||
$AverageValue = ($AverageCalc[$calc].Sum / $AverageCalc[$calc].Count);
|
|
||||||
[string]$MetricName = Format-IcingaPerfDataLabel (
|
|
||||||
[string]::Format('{0}_{1}', $HashIndex, $AverageCalc[$calc].Interval)
|
|
||||||
);
|
|
||||||
|
|
||||||
Add-IcingaHashtableItem `
|
|
||||||
-Hashtable $global:Icinga.CheckData[$CheckCommand]['average'] `
|
|
||||||
-Key $MetricName -Value $AverageValue -Override | Out-Null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$AverageCalc[$calc].Sum = 0;
|
|
||||||
$AverageCalc[$calc].Count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Flush data we no longer require in our cache to free memory
|
|
||||||
[array]$CheckStores = $global:Icinga.CheckData[$CheckCommand]['results'].Keys;
|
|
||||||
|
|
||||||
foreach ($CheckStore in $CheckStores) {
|
|
||||||
[string]$CheckKey = $CheckStore;
|
|
||||||
[array]$CheckTimeStamps = $global:Icinga.CheckData[$CheckCommand]['results'][$CheckKey].Keys;
|
|
||||||
|
|
||||||
foreach ($TimeSample in $CheckTimeStamps) {
|
|
||||||
if (($UnixTime - $MaxTimeInSeconds) -gt [int]$TimeSample) {
|
|
||||||
Remove-IcingaHashtableItem -Hashtable $global:Icinga.CheckData[$CheckCommand]['results'][$CheckKey] -Key ([string]$TimeSample);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Set-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult' -KeyName $CheckCommand -Value $global:Icinga.CheckData[$CheckCommand]['average'];
|
|
||||||
# Write collected metrics to disk in case we reload the daemon. We will load them back into the module after reload then
|
|
||||||
Set-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult_store' -KeyName $CheckCommand -Value $PerfCache;
|
|
||||||
} catch {
|
|
||||||
# Just for debugging. Not required in production or usable at all
|
|
||||||
$ErrMsg = $_.Exception.Message;
|
|
||||||
Write-IcingaConsoleError 'Failed to handle check result processing: {0}' -Objects $ErrMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Always ensure our check data is cleared regardless of possible
|
|
||||||
# exceptions which might occur
|
|
||||||
Get-IcingaCheckSchedulerPerfData | Out-Null;
|
|
||||||
Get-IcingaCheckSchedulerPluginOutput | Out-Null;
|
|
||||||
|
|
||||||
$PassedTime = 0;
|
|
||||||
$SortedResult.Clear();
|
|
||||||
$PerfCache.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
$PassedTime += 1;
|
|
||||||
Start-Sleep -Seconds 1;
|
|
||||||
# Force Icinga for Windows Garbage Collection
|
|
||||||
Optimize-IcingaForWindowsMemory -ClearErrorStack;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
A background daemon executing registered service checks in the background to fetch
|
|
||||||
metrics for certain checks over time. Time frames are configurable individual
|
|
||||||
.DESCRIPTION
|
|
||||||
This background daemon will execute checks registered with "Register-IcingaServiceCheck"
|
|
||||||
for the given time interval and store the collected metrics for a defined period of time
|
|
||||||
inside a JSON file. Check values collected by this daemon are then automatically added
|
|
||||||
to regular check executions for additional performance metrics.
|
|
||||||
|
|
||||||
Example: Register-IcingaServiceCheck -CheckCommand 'Invoke-IcingaCheckCPU' -Interval 30 -TimeIndexes 1,3,5,15;
|
|
||||||
|
|
||||||
This will execute the CPU check every 30 seconds and calculate the average of 1, 3, 5 and 15 minutes
|
|
||||||
|
|
||||||
More Information on
|
|
||||||
https://icinga.com/docs/icinga-for-windows/latest/doc/service/02-Register-Daemons/
|
|
||||||
https://icinga.com/docs/icinga-for-windows/latest/doc/service/10-Register-Service-Checks/
|
|
||||||
.LINK
|
|
||||||
https://github.com/Icinga/icinga-powershell-framework
|
|
||||||
.NOTES
|
|
||||||
#>
|
|
||||||
|
|
||||||
function Start-IcingaServiceCheckDaemon()
|
|
||||||
{
|
|
||||||
New-IcingaThreadInstance -Name "Icinga_PowerShell_ServiceCheck_Scheduler" -ThreadPool $IcingaDaemonData.IcingaThreadPool.BackgroundPool -Command 'Add-IcingaServiceCheckDaemon' -CmdParameters @{ 'IcingaDaemonData' = $global:IcingaDaemonData } -Start;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Add-IcingaServiceCheckDaemon()
|
|
||||||
{
|
|
||||||
param (
|
|
||||||
$IcingaDaemonData
|
|
||||||
);
|
|
||||||
|
|
||||||
Use-Icinga -LibOnly -Daemon;
|
|
||||||
|
|
||||||
$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;
|
|
||||||
}
|
|
||||||
|
|
||||||
[hashtable]$ServiceArgs = @{ };
|
|
||||||
|
|
||||||
if ($null -ne $RegisteredServices[$service].Arguments) {
|
|
||||||
foreach ($property in $RegisteredServices[$service].Arguments.PSObject.Properties) {
|
|
||||||
if ($ServiceArgs.ContainsKey($property.Name)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$ServiceArgs.Add($property.Name, $property.Value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Start-IcingaServiceCheckTask -CheckId $service -CheckCommand $RegisteredServices[$service].CheckCommand -Arguments $ServiceArgs -Interval $RegisteredServices[$service].Interval -TimeIndexes $RegisteredServices[$service].TimeIndexes;
|
|
||||||
}
|
|
||||||
Start-Sleep -Seconds 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Start-IcingaServiceCheckTask()
|
|
||||||
{
|
|
||||||
param(
|
|
||||||
$CheckId,
|
|
||||||
$CheckCommand,
|
|
||||||
$Arguments,
|
|
||||||
$Interval,
|
|
||||||
$TimeIndexes
|
|
||||||
);
|
|
||||||
|
|
||||||
[string]$ThreadName = [string]::Format('Icinga_Background_Service_Check_{0}', $CheckId);
|
|
||||||
|
|
||||||
New-IcingaThreadInstance -Name $ThreadName -ThreadPool $IcingaDaemonData.IcingaThreadPool.ServiceCheckPool -Command 'Add-IcingaServiceCheckTask' -CmdParameters @{
|
|
||||||
'IcingaDaemonData' = $global:IcingaDaemonData;
|
|
||||||
'CheckCommand' = $CheckCommand;
|
|
||||||
'Arguments' = $Arguments;
|
|
||||||
'Interval' = $Interval;
|
|
||||||
'TimeIndexes' = $TimeIndexes
|
|
||||||
'CheckId' = $CheckId;
|
|
||||||
} -Start;
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
function Add-IcingaServiceCheckDaemon()
|
||||||
|
{
|
||||||
|
Add-IcingaThreadPool -Name 'ServiceCheckPool' -MaxInstances 100;
|
||||||
|
|
||||||
|
[hashtable]$KnownChecks = @{ };
|
||||||
|
|
||||||
|
$Global:Icinga.Public.Daemons.Add(
|
||||||
|
'ServiceCheck',
|
||||||
|
@{
|
||||||
|
'PerformanceDataCache' = @{ }
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
while ($TRUE) {
|
||||||
|
|
||||||
|
# Load the configuration file to be aware of service check changes
|
||||||
|
$RegisteredServices = Get-IcingaRegisteredServiceChecks;
|
||||||
|
|
||||||
|
# Debugging message
|
||||||
|
Write-IcingaDebugMessage 'Found these service checks to load within service check daemon: {0}' -Objects ($RegisteredServices.Keys | Out-String);
|
||||||
|
|
||||||
|
# Loop all found background services and create a new thread for each check
|
||||||
|
foreach ($service in $RegisteredServices.Keys) {
|
||||||
|
[string]$ThreadName = [string]::Format('Start-IcingaServiceCheckTask::Add-IcingaServiceCheckTask::{0}::0', $service);
|
||||||
|
|
||||||
|
# In case the check is already being executed, continue
|
||||||
|
if ((Test-IcingaThread -Thread $ThreadName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get all possible arguments for this check
|
||||||
|
[hashtable]$ServiceArgs = @{ };
|
||||||
|
|
||||||
|
if ($null -ne $RegisteredServices[$service].Arguments) {
|
||||||
|
foreach ($property in $RegisteredServices[$service].Arguments.PSObject.Properties) {
|
||||||
|
if ($ServiceArgs.ContainsKey($property.Name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ServiceArgs.Add($property.Name, $property.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add the check to our cache, ensuring that we are aware of modifications during runtime
|
||||||
|
if ($KnownChecks.ContainsKey($service) -eq $FALSE) {
|
||||||
|
$KnownChecks.Add($service, $TRUE);
|
||||||
|
} else {
|
||||||
|
$KnownChecks[$service] = $TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Start a new thread for executing the check
|
||||||
|
Start-IcingaServiceCheckTask `
|
||||||
|
-CheckId $service `
|
||||||
|
-CheckCommand $RegisteredServices[$service].CheckCommand `
|
||||||
|
-Arguments $ServiceArgs `
|
||||||
|
-Interval $RegisteredServices[$service].Interval `
|
||||||
|
-TimeIndexes $RegisteredServices[$service].TimeIndexes;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
[array]$KnownCheckIds = $KnownChecks.Keys;
|
||||||
|
|
||||||
|
foreach ($entry in $KnownCheckIds) {
|
||||||
|
if ($RegisteredServices.ContainsKey($entry)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$KnownChecks[$entry] = $FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($entry in $KnownCheckIds) {
|
||||||
|
if ($KnownChecks[$entry] -eq $FALSE) {
|
||||||
|
$KnownChecks.Remove($entry);
|
||||||
|
|
||||||
|
[string]$ThreadName = [string]::Format('Start-IcingaServiceCheckTask::Add-IcingaServiceCheckTask::{0}::0', $entry);
|
||||||
|
|
||||||
|
Remove-IcingaThread -Thread $ThreadName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Optimize-IcingaForWindowsMemory;
|
||||||
|
|
||||||
|
Start-Sleep -Seconds 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
A background daemon executing registered service checks in the background to fetch
|
||||||
|
metrics for certain checks over time. Time frames are configurable individual
|
||||||
|
.DESCRIPTION
|
||||||
|
This background daemon will execute checks registered with "Register-IcingaServiceCheck"
|
||||||
|
for the given time interval and store the collected metrics for a defined period of time
|
||||||
|
inside a JSON file. Check values collected by this daemon are then automatically added
|
||||||
|
to regular check executions for additional performance metrics.
|
||||||
|
|
||||||
|
Example: Register-IcingaServiceCheck -CheckCommand 'Invoke-IcingaCheckCPU' -Interval 30 -TimeIndexes 1,3,5,15;
|
||||||
|
|
||||||
|
This will execute the CPU check every 30 seconds and calculate the average of 1, 3, 5 and 15 minutes
|
||||||
|
|
||||||
|
More Information on
|
||||||
|
https://icinga.com/docs/icinga-for-windows/latest/doc/service/02-Register-Daemons/
|
||||||
|
https://icinga.com/docs/icinga-for-windows/latest/doc/service/10-Register-Service-Checks/
|
||||||
|
.LINK
|
||||||
|
https://github.com/Icinga/icinga-powershell-framework
|
||||||
|
.NOTES
|
||||||
|
#>
|
||||||
|
|
||||||
|
function Start-IcingaServiceCheckDaemon()
|
||||||
|
{
|
||||||
|
New-IcingaThreadInstance `
|
||||||
|
-Name 'Main' `
|
||||||
|
-ThreadPool (Get-IcingaThreadPool -Name 'MainPool') `
|
||||||
|
-Command 'Add-IcingaServiceCheckDaemon' `
|
||||||
|
-Start;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
function Add-IcingaServiceCheckTask()
|
||||||
|
{
|
||||||
|
param (
|
||||||
|
$CheckCommand,
|
||||||
|
$Arguments,
|
||||||
|
$Interval,
|
||||||
|
$TimeIndexes,
|
||||||
|
$CheckId
|
||||||
|
);
|
||||||
|
|
||||||
|
# $Global:Icinga.Private.Daemons.ServiceCheck
|
||||||
|
New-IcingaServiceCheckDaemonEnvironment `
|
||||||
|
-CheckCommand $CheckCommand `
|
||||||
|
-Arguments $Arguments `
|
||||||
|
-TimeIndexes $TimeIndexes;
|
||||||
|
|
||||||
|
# Read our check result store data from disk for this service check
|
||||||
|
Read-IcingaCheckResultStore -CheckCommand $CheckCommand;
|
||||||
|
|
||||||
|
while ($TRUE) {
|
||||||
|
if ($Global:Icinga.Private.Daemons.ServiceCheck.PassedTime -lt $Interval) {
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.PassedTime += 1;
|
||||||
|
Start-Sleep -Seconds 1;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.PassedTime = 0;
|
||||||
|
|
||||||
|
# Execute our check with possible arguments
|
||||||
|
try {
|
||||||
|
& $CheckCommand @Arguments | Out-Null;
|
||||||
|
} catch {
|
||||||
|
Write-IcingaEventMessage -EventId 1451 -Namespace 'Framework' -ExceptionObject $_ -Objects $CheckCommand, ($Arguments | Out-String), (Get-IcingaInternalPluginOutput);
|
||||||
|
|
||||||
|
Clear-IcingaCheckSchedulerEnvironment;
|
||||||
|
|
||||||
|
# Force Icinga for Windows Garbage Collection
|
||||||
|
Optimize-IcingaForWindowsMemory -ClearErrorStack;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$UnixTime = Get-IcingaUnixTime;
|
||||||
|
|
||||||
|
try {
|
||||||
|
foreach ($result in $global:Icinga.Private.Scheduler.CheckData[$CheckCommand]['results'].Keys) {
|
||||||
|
[string]$HashIndex = $result;
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.SortedResult = $global:Icinga.Private.Scheduler.CheckData[$CheckCommand]['results'][$HashIndex].GetEnumerator() | Sort-Object name -Descending;
|
||||||
|
|
||||||
|
Add-IcingaHashtableItem `
|
||||||
|
-Hashtable $Global:Icinga.Private.Daemons.ServiceCheck.PerformanceCache `
|
||||||
|
-Key $HashIndex `
|
||||||
|
-Value @{ } | Out-Null;
|
||||||
|
|
||||||
|
foreach ($timeEntry in $Global:Icinga.Private.Daemons.ServiceCheck.SortedResult) {
|
||||||
|
|
||||||
|
if ((Test-Numeric $timeEntry.Value) -eq $FALSE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($calc in $Global:Icinga.Private.Daemons.ServiceCheck.AverageCalculation.Keys) {
|
||||||
|
if (($UnixTime - $Global:Icinga.Private.Daemons.ServiceCheck.AverageCalculation[$calc].Time) -le [int]$timeEntry.Key) {
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.AverageCalculation[$calc].Sum += $timeEntry.Value;
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.AverageCalculation[$calc].Count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (($UnixTime - $Global:Icinga.Private.Daemons.ServiceCheck.MaxTimeInSeconds) -le [int]$timeEntry.Key) {
|
||||||
|
Add-IcingaHashtableItem `
|
||||||
|
-Hashtable $Global:Icinga.Private.Daemons.ServiceCheck.PerformanceCache[$HashIndex] `
|
||||||
|
-Key ([string]$timeEntry.Key) `
|
||||||
|
-Value ([string]$timeEntry.Value) | Out-Null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($calc in $Global:Icinga.Private.Daemons.ServiceCheck.AverageCalculation.Keys) {
|
||||||
|
if ($Global:Icinga.Private.Daemons.ServiceCheck.AverageCalculation[$calc].Count -ne 0) {
|
||||||
|
$AverageValue = ($Global:Icinga.Private.Daemons.ServiceCheck.AverageCalculation[$calc].Sum / $Global:Icinga.Private.Daemons.ServiceCheck.AverageCalculation[$calc].Count);
|
||||||
|
[string]$MetricName = Format-IcingaPerfDataLabel (
|
||||||
|
[string]::Format('{0}_{1}', $HashIndex, $Global:Icinga.Private.Daemons.ServiceCheck.AverageCalculation[$calc].Interval)
|
||||||
|
);
|
||||||
|
|
||||||
|
$Global:Icinga.Private.Scheduler.CheckData[$CheckCommand]['average'] | Add-Member -MemberType NoteProperty -Name $MetricName -Value $AverageValue -Force;
|
||||||
|
}
|
||||||
|
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.AverageCalculation[$calc].Sum = 0;
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.AverageCalculation[$calc].Count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-IcingaDebugMessage `
|
||||||
|
-Message 'Object dump of service check daemon' `
|
||||||
|
-Objects @(
|
||||||
|
$CheckCommand,
|
||||||
|
'Average Calc',
|
||||||
|
($Global:Icinga.Private.Daemons.ServiceCheck.AverageCalculation | Out-String),
|
||||||
|
'PerformanceCache',
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.PerformanceCache,
|
||||||
|
'Max Time in Seconds',
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.MaxTimeInSeconds,
|
||||||
|
'Unix Time',
|
||||||
|
$UnixTime
|
||||||
|
);
|
||||||
|
|
||||||
|
# Flush data we no longer require in our cache to free memory
|
||||||
|
[array]$CheckStores = $Global:Icinga.Private.Scheduler.CheckData[$CheckCommand]['results'].Keys;
|
||||||
|
|
||||||
|
foreach ($CheckStore in $CheckStores) {
|
||||||
|
[string]$CheckKey = $CheckStore;
|
||||||
|
[array]$CheckTimeStamps = $global:Icinga.Private.Scheduler.CheckData[$CheckCommand]['results'][$CheckKey].Keys;
|
||||||
|
|
||||||
|
foreach ($TimeSample in $CheckTimeStamps) {
|
||||||
|
if (($UnixTime - $Global:Icinga.Private.Daemons.ServiceCheck.MaxTimeInSeconds) -gt [int]$TimeSample) {
|
||||||
|
Remove-IcingaHashtableItem -Hashtable $global:Icinga.Private.Scheduler.CheckData[$CheckCommand]['results'][$CheckKey] -Key ([string]$TimeSample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Set-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult' -KeyName $CheckCommand -Value $global:Icinga.Private.Scheduler.CheckData[$CheckCommand]['average'];
|
||||||
|
|
||||||
|
# Make the performance data available for all threads
|
||||||
|
$Global:Icinga.Public.Daemons.ServiceCheck.PerformanceDataCache[$CheckCommand] = $global:Icinga.Private.Scheduler.CheckData[$CheckCommand]['average'];
|
||||||
|
# Write collected metrics to disk in case we reload the daemon. We will load them back into the module after reload then
|
||||||
|
Set-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult_store' -KeyName $CheckCommand -Value $Global:Icinga.Private.Daemons.ServiceCheck.PerformanceCache;
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
Write-IcingaEventMessage -EventId 1452 -Namespace 'Framework' -ExceptionObject $_ -Objects $CheckCommand, ($Arguments | Out-String), (Get-IcingaInternalPluginOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Always ensure our check data is cleared regardless of possible
|
||||||
|
# exceptions which might occur
|
||||||
|
Clear-IcingaCheckSchedulerEnvironment;
|
||||||
|
# Reset certain values from the scheduler environment
|
||||||
|
Clear-IcingaServiceCheckDaemonEnvironment;
|
||||||
|
# Force Icinga for Windows Garbage Collection
|
||||||
|
Optimize-IcingaForWindowsMemory -ClearErrorStack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
function Start-IcingaServiceCheckTask()
|
||||||
|
{
|
||||||
|
param (
|
||||||
|
$CheckId,
|
||||||
|
$CheckCommand,
|
||||||
|
$Arguments,
|
||||||
|
$Interval,
|
||||||
|
$TimeIndexes
|
||||||
|
);
|
||||||
|
|
||||||
|
New-IcingaThreadInstance -Name $CheckId -ThreadPool (Get-IcingaThreadPool -Name 'ServiceCheckPool') -Command 'Add-IcingaServiceCheckTask' -CmdParameters @{
|
||||||
|
'CheckCommand' = $CheckCommand;
|
||||||
|
'Arguments' = $Arguments;
|
||||||
|
'Interval' = $Interval;
|
||||||
|
'TimeIndexes' = $TimeIndexes
|
||||||
|
'CheckId' = $CheckId;
|
||||||
|
} -Start;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
function Clear-IcingaServiceCheckDaemonEnvironment()
|
||||||
|
{
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.PassedTime = 0;
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.SortedResult.Clear();
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.PerformanceCache.Clear();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
function New-IcingaServiceCheckDaemonEnvironment()
|
||||||
|
{
|
||||||
|
param (
|
||||||
|
$CheckCommand,
|
||||||
|
$Arguments,
|
||||||
|
$TimeIndexes
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($Global:Icinga.Public.Daemons.ServiceCheck.PerformanceDataCache.ContainsKey($CheckCommand) -eq $FALSE) {
|
||||||
|
$Global:Icinga.Public.Daemons.ServiceCheck.PerformanceDataCache.Add(
|
||||||
|
$CheckCommand, @{ }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$Global:Icinga.Private.Daemons.Add(
|
||||||
|
'ServiceCheck',
|
||||||
|
@{
|
||||||
|
'PassedTime' = 0;
|
||||||
|
'SortedResult' = $null;
|
||||||
|
'PerformanceCache' = @{ };
|
||||||
|
'AverageCalculation' = @{ };
|
||||||
|
'MaxTime' = 0;
|
||||||
|
'MaxTimeInSeconds' = 0;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($index in $TimeIndexes) {
|
||||||
|
# Only allow numeric index values
|
||||||
|
if ((Test-Numeric $index) -eq $FALSE) {
|
||||||
|
Write-IcingaEventMessage -EventId 1450 -Namespace 'Framework' -Objects $CheckCommand, ($Arguments | Out-String), ($TimeIndexes | Out-String), $index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($Global:Icinga.Private.Daemons.ServiceCheck.AverageCalculation.ContainsKey([string]$index) -eq $FALSE) {
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.AverageCalculation.Add(
|
||||||
|
[string]$index,
|
||||||
|
@{
|
||||||
|
'Interval' = ([int]$index);
|
||||||
|
'Time' = ([int]$index * 60);
|
||||||
|
'Sum' = 0;
|
||||||
|
'Count' = 0;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ($Global:Icinga.Private.Daemons.ServiceCheck.MaxTime -le [int]$index) {
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.MaxTime = [int]$index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Global:Icinga.Private.Daemons.ServiceCheck.MaxTimeInSeconds = $Global:Icinga.Private.Daemons.ServiceCheck.MaxTime * 60;
|
||||||
|
|
||||||
|
if ($Global:Icinga.Private.Scheduler.CheckData.ContainsKey($CheckCommand) -eq $FALSE) {
|
||||||
|
$Global:Icinga.Private.Scheduler.CheckData.Add(
|
||||||
|
$CheckCommand,
|
||||||
|
@{
|
||||||
|
'results' = @{ };
|
||||||
|
'average' = (New-Object -TypeName PSObject);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
function Read-IcingaCheckResultStore()
|
||||||
|
{
|
||||||
|
param (
|
||||||
|
$CheckCommand
|
||||||
|
);
|
||||||
|
|
||||||
|
$LoadedCacheData = Get-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult_store' -KeyName $CheckCommand;
|
||||||
|
|
||||||
|
if ($null -ne $LoadedCacheData) {
|
||||||
|
foreach ($entry in $LoadedCacheData.PSObject.Properties) {
|
||||||
|
$Global:Icinga.Private.Scheduler.CheckData[$CheckCommand]['results'].Add(
|
||||||
|
$entry.name,
|
||||||
|
@{ }
|
||||||
|
);
|
||||||
|
foreach ($item in $entry.Value.PSObject.Properties) {
|
||||||
|
$Global:Icinga.Private.Scheduler.CheckData[$CheckCommand]['results'][$entry.name].Add(
|
||||||
|
$item.Name,
|
||||||
|
$item.Value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,21 +3,13 @@ function Invoke-IcingaApiChecksRESTCall()
|
||||||
param (
|
param (
|
||||||
[Hashtable]$Request = @{ },
|
[Hashtable]$Request = @{ },
|
||||||
[Hashtable]$Connection = @{ },
|
[Hashtable]$Connection = @{ },
|
||||||
$IcingaGlobals,
|
|
||||||
[string]$ApiVersion = $null
|
[string]$ApiVersion = $null
|
||||||
);
|
);
|
||||||
|
|
||||||
$Global:IcingaDaemonData = $IcingaGlobals;
|
|
||||||
|
|
||||||
# Initialise some global variables we use to actually store check result data from
|
|
||||||
# plugins properly. This is doable from each thread instance as this part isn't
|
|
||||||
# shared between daemons
|
|
||||||
New-IcingaCheckSchedulerEnvironment;
|
|
||||||
|
|
||||||
[Hashtable]$ContentResponse = @{ };
|
[Hashtable]$ContentResponse = @{ };
|
||||||
|
|
||||||
# Short our call
|
# Short our call
|
||||||
$CheckerAliases = $IcingaGlobals.BackgroundDaemon.IcingaPowerShellRestApi.CommandAliases.checker;
|
$CheckerAliases = $Global:Icinga.Public.Daemons.RESTApi.CommandAliases.checker;
|
||||||
$CheckConfig = $Request.Body;
|
$CheckConfig = $Request.Body;
|
||||||
[int]$ExitCode = 3; #Unknown
|
[int]$ExitCode = 3; #Unknown
|
||||||
|
|
||||||
|
|
@ -117,7 +109,7 @@ function Invoke-IcingaApiChecksRESTCall()
|
||||||
}
|
}
|
||||||
|
|
||||||
# Free our memory again
|
# Free our memory again
|
||||||
Clear-IcingaCheckSchedulerEnvironment;
|
Clear-IcingaCheckSchedulerEnvironment -ClearCheckData;
|
||||||
|
|
||||||
Write-IcingaDebugMessage -Message 'Check Executed. Result below' -Objects $ExecuteCommand, $CheckResult, $PerfData, $ExitCode;
|
Write-IcingaDebugMessage -Message 'Check Executed. Result below' -Objects $ExecuteCommand, $CheckResult, $PerfData, $ExitCode;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ function Exit-IcingaThrowCritical()
|
||||||
Set-IcingaInternalPluginExitCode -ExitCode $IcingaEnums.IcingaExitCode.Critical;
|
Set-IcingaInternalPluginExitCode -ExitCode $IcingaEnums.IcingaExitCode.Critical;
|
||||||
Set-IcingaInternalPluginException -PluginException $OutputMessage;
|
Set-IcingaInternalPluginException -PluginException $OutputMessage;
|
||||||
|
|
||||||
if ($null -eq $global:IcingaDaemonData -Or ($global:IcingaDaemonData.FrameworkRunningAsDaemon -eq $FALSE -And $global:IcingaDaemonData.JEAContext -eq $FALSE)) {
|
if ($Global:Icinga.Protected.RunAsDaemon -eq $FALSE -And $Global:Icinga.Protected.JEAContext -eq $FALSE) {
|
||||||
Write-IcingaConsolePlain $OutputMessage;
|
Write-IcingaConsolePlain $OutputMessage;
|
||||||
exit $IcingaEnums.IcingaExitCode.Critical;
|
exit $IcingaEnums.IcingaExitCode.Critical;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ function Exit-IcingaThrowException()
|
||||||
Set-IcingaInternalPluginExitCode -ExitCode $IcingaEnums.IcingaExitCode.Unknown;
|
Set-IcingaInternalPluginExitCode -ExitCode $IcingaEnums.IcingaExitCode.Unknown;
|
||||||
Set-IcingaInternalPluginException -PluginException $OutputMessage;
|
Set-IcingaInternalPluginException -PluginException $OutputMessage;
|
||||||
|
|
||||||
if ($null -eq $global:IcingaDaemonData -Or ($global:IcingaDaemonData.FrameworkRunningAsDaemon -eq $FALSE -And $global:IcingaDaemonData.JEAContext -eq $FALSE)) {
|
if ($Global:Icinga.Protected.RunAsDaemon -eq $FALSE -And $Global:Icinga.Protected.JEAContext -eq $FALSE) {
|
||||||
Write-IcingaConsolePlain $OutputMessage;
|
Write-IcingaConsolePlain $OutputMessage;
|
||||||
exit $IcingaEnums.IcingaExitCode.Unknown;
|
exit $IcingaEnums.IcingaExitCode.Unknown;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ function Exit-IcingaExecutePlugin()
|
||||||
& powershell.exe -ConfigurationName $JEAProfile -NoLogo -NoProfile -Command {
|
& powershell.exe -ConfigurationName $JEAProfile -NoLogo -NoProfile -Command {
|
||||||
Use-Icinga;
|
Use-Icinga;
|
||||||
|
|
||||||
$global:IcingaDaemonData.JEAContext = $TRUE;
|
$Global:Icinga.Protected.JEAContext = $TRUE;
|
||||||
|
|
||||||
$Command = $args[0];
|
$Command = $args[0];
|
||||||
$Arguments = $args[1];
|
$Arguments = $args[1];
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
function Get-IcingaInternalPluginExitCode()
|
function Get-IcingaInternalPluginExitCode()
|
||||||
{
|
{
|
||||||
return $Global:Icinga.PluginExecution.LastExitCode;
|
return $Global:Icinga.Private.Scheduler.ExitCode;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
function Get-IcingaInternalPluginOutput()
|
function Get-IcingaInternalPluginOutput()
|
||||||
{
|
{
|
||||||
if ([string]::IsNullOrEmpty($Global:Icinga.PluginExecution.PluginException) -eq $FALSE) {
|
if ([string]::IsNullOrEmpty($Global:Icinga.Private.Scheduler.PluginException) -eq $FALSE) {
|
||||||
return $Global:Icinga.PluginExecution.PluginException;
|
return $Global:Icinga.Private.Scheduler.PluginException;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $Global:Icinga.CheckResults;
|
return $Global:Icinga.Private.Scheduler.CheckResults;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,17 +8,9 @@ function Get-IcingaThresholdCache()
|
||||||
return $null;
|
return $null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($null -eq $Global:Icinga) {
|
if ($Global:Icinga.Private.Scheduler.ThresholdCache.ContainsKey($CheckCommand) -eq $FALSE) {
|
||||||
return $null;
|
return $null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($Global:Icinga.ContainsKey('ThresholdCache') -eq $FALSE) {
|
return $Global:Icinga.Private.Scheduler.ThresholdCache[$CheckCommand];
|
||||||
return $null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($Global:Icinga.ThresholdCache.ContainsKey($CheckCommand) -eq $FALSE) {
|
|
||||||
return $null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $Global:Icinga.ThresholdCache[$CheckCommand];
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -287,16 +287,11 @@ function New-IcingaCheck()
|
||||||
$IcingaCheck | Add-Member -MemberType ScriptMethod -Name '__AddCheckDataToCache' -Value {
|
$IcingaCheck | Add-Member -MemberType ScriptMethod -Name '__AddCheckDataToCache' -Value {
|
||||||
|
|
||||||
# We only require this in case we are running as daemon
|
# We only require this in case we are running as daemon
|
||||||
if ([string]::IsNullOrEmpty($this.__CheckCommand) -Or $global:IcingaDaemonData.FrameworkRunningAsDaemon -eq $FALSE) {
|
if ([string]::IsNullOrEmpty($this.__CheckCommand) -Or $Global:Icinga.Protected.RunAsDaemon -eq $FALSE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
# If no check table has been created, do nothing
|
if ($global:Icinga.Private.Scheduler.CheckData.ContainsKey($this.__CheckCommand) -eq $FALSE) {
|
||||||
if ($null -eq $global:Icinga -Or $global:Icinga.ContainsKey('CheckData') -eq $FALSE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($global:Icinga.CheckData.ContainsKey($this.__CheckCommand) -eq $FALSE) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -304,8 +299,8 @@ function New-IcingaCheck()
|
||||||
# and check execution within the same time slot because of this
|
# and check execution within the same time slot because of this
|
||||||
[string]$TimeIndex = Get-IcingaUnixTime;
|
[string]$TimeIndex = Get-IcingaUnixTime;
|
||||||
|
|
||||||
Add-IcingaHashtableItem -Hashtable $global:Icinga.CheckData[$this.__CheckCommand]['results'] -Key $this.Name -Value @{ } | Out-Null;
|
Add-IcingaHashtableItem -Hashtable $global:Icinga.Private.Scheduler.CheckData[$this.__CheckCommand]['results'] -Key $this.Name -Value @{ } | Out-Null;
|
||||||
Add-IcingaHashtableItem -Hashtable $global:Icinga.CheckData[$this.__CheckCommand]['results'][$this.Name] -Key $TimeIndex -Value $this.Value -Override | Out-Null;
|
Add-IcingaHashtableItem -Hashtable $global:Icinga.Private.Scheduler.CheckData[$this.__CheckCommand]['results'][$this.Name] -Key $TimeIndex -Value $this.Value -Override | Out-Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$IcingaCheck | Add-Member -MemberType ScriptMethod -Name 'SetOk' -Value {
|
$IcingaCheck | Add-Member -MemberType ScriptMethod -Name 'SetOk' -Value {
|
||||||
|
|
|
||||||
|
|
@ -29,23 +29,20 @@ function New-IcingaCheckBaseObject()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($null -eq $Global:Icinga) {
|
if ($Global:Icinga.Private.Scheduler.ThresholdCache.ContainsKey($this.__CheckCommand) -eq $FALSE) {
|
||||||
$Global:Icinga = @{ };
|
$Global:Icinga.Private.Scheduler.ThresholdCache.Add($this.__CheckCommand, $null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($Global:Icinga.ContainsKey('ThresholdCache') -eq $FALSE) {
|
if ($null -ne $Global:Icinga.Private.Scheduler.ThresholdCache[$this.__CheckCommand]) {
|
||||||
$Global:Icinga.Add('ThresholdCache', @{ });
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($Global:Icinga.ThresholdCache.ContainsKey($this.__CheckCommand) -eq $FALSE) {
|
|
||||||
$Global:Icinga.ThresholdCache.Add($this.__CheckCommand, $null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($null -ne $Global:Icinga.ThresholdCache[$this.__CheckCommand]) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$Global:Icinga.ThresholdCache[$this.__CheckCommand] = (Get-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult' -KeyName $this.__CheckCommand);
|
if ($Global:Icinga.Public.Daemons.ContainsKey('ServiceCheck') -And $Global:Icinga.Public.Daemons.ServiceCheck.PerformanceDataCache.ContainsKey($this.__CheckCommand) -And $Global:Icinga.Public.Daemons.ServiceCheck.PerformanceDataCache[$CheckCommand].Count -ne 0) {
|
||||||
|
$Global:Icinga.Private.Scheduler.ThresholdCache[$this.__CheckCommand] = $Global:Icinga.Public.Daemons.ServiceCheck.PerformanceDataCache[$CheckCommand];
|
||||||
|
} else {
|
||||||
|
# Fallback in case the service is not registered within the daemon or we are running a plugin from without the daemon environment
|
||||||
|
$Global:Icinga.Private.Scheduler.ThresholdCache[$this.__CheckCommand] = (Get-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult' -KeyName $this.__CheckCommand);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$IcingaCheckBaseObject | Add-Member -MemberType ScriptMethod -Name '__SetParent' -Value {
|
$IcingaCheckBaseObject | Add-Member -MemberType ScriptMethod -Name '__SetParent' -Value {
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ function New-IcingaCheckResult()
|
||||||
|
|
||||||
# Ensure we reset our internal cache once the plugin was executed
|
# Ensure we reset our internal cache once the plugin was executed
|
||||||
$CheckCommand = $this.Check.__GetCheckCommand();
|
$CheckCommand = $this.Check.__GetCheckCommand();
|
||||||
if ([string]::IsNullOrEmpty($CheckCommand) -eq $FALSE -And $Global:Icinga.ThresholdCache.ContainsKey($CheckCommand)) {
|
if ([string]::IsNullOrEmpty($CheckCommand) -eq $FALSE -And $Global:Icinga.Private.Scheduler.ThresholdCache.ContainsKey($CheckCommand)) {
|
||||||
$Global:Icinga.ThresholdCache[$CheckCommand] = $null;
|
$Global:Icinga.Private.Scheduler.ThresholdCache[$CheckCommand] = $null;
|
||||||
}
|
}
|
||||||
# Reset the current execution date
|
# Reset the current execution date
|
||||||
$Global:Icinga.CurrentDate = $null;
|
$Global:Icinga.CurrentDate = $null;
|
||||||
|
|
|
||||||
|
|
@ -4,26 +4,8 @@ function Set-IcingaInternalPluginException()
|
||||||
[string]$PluginException = ''
|
[string]$PluginException = ''
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($null -eq $Global:Icinga) {
|
# Only catch the first exception
|
||||||
$Global:Icinga = @{ };
|
if ([string]::IsNullOrEmpty($Global:Icinga.Private.Scheduler.PluginException)) {
|
||||||
}
|
$Global:Icinga.Private.Scheduler.PluginException = $PluginException;
|
||||||
|
|
||||||
if ($Global:Icinga.ContainsKey('PluginExecution') -eq $FALSE) {
|
|
||||||
$Global:Icinga.Add(
|
|
||||||
'PluginExecution',
|
|
||||||
@{
|
|
||||||
'PluginException' = $PluginException;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
if ($Global:Icinga.PluginExecution.ContainsKey('PluginException') -eq $FALSE) {
|
|
||||||
$Global:Icinga.PluginExecution.Add('PluginException', $PluginException);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Only catch the first exception
|
|
||||||
if ([string]::IsNullOrEmpty($Global:Icinga.PluginExecution.PluginException)) {
|
|
||||||
$Global:Icinga.PluginExecution.PluginException = $PluginException;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,26 +4,8 @@ function Set-IcingaInternalPluginExitCode()
|
||||||
$ExitCode = 0
|
$ExitCode = 0
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($null -eq $Global:Icinga) {
|
# Only add the first exit code we should cover during one runtime
|
||||||
$Global:Icinga = @{ };
|
if ($null -eq $Global:Icinga.Private.Scheduler.ExitCode) {
|
||||||
}
|
$Global:Icinga.Private.Scheduler.ExitCode = $ExitCode;
|
||||||
|
|
||||||
if ($Global:Icinga.ContainsKey('PluginExecution') -eq $FALSE) {
|
|
||||||
$Global:Icinga.Add(
|
|
||||||
'PluginExecution',
|
|
||||||
@{
|
|
||||||
'LastExitCode' = $ExitCode;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
if ($Global:Icinga.PluginExecution.ContainsKey('LastExitCode') -eq $FALSE) {
|
|
||||||
$Global:Icinga.PluginExecution.Add('LastExitCode', $ExitCode);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Only add the first exit code we should cover during one runtime
|
|
||||||
if ($null -eq $Global:Icinga.PluginExecution.LastExitCode) {
|
|
||||||
$Global:Icinga.PluginExecution.LastExitCode = $ExitCode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,13 @@ function Write-IcingaPluginOutput()
|
||||||
$Output
|
$Output
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($global:IcingaDaemonData.FrameworkRunningAsDaemon -eq $FALSE -And $global:IcingaDaemonData.JEAContext -eq $FALSE) {
|
if ($Global:Icinga.Protected.RunAsDaemon -eq $FALSE -And $Global:Icinga.Protected.JEAContext -eq $FALSE) {
|
||||||
if ($null -ne $global:Icinga -And $global:Icinga.Minimal) {
|
if ($Global:Icinga.Protected.Minimal) {
|
||||||
Clear-Host;
|
Clear-Host;
|
||||||
}
|
}
|
||||||
Write-IcingaConsolePlain $Output;
|
Write-IcingaConsolePlain $Output;
|
||||||
} else {
|
} else {
|
||||||
# New behavior with local thread separated results
|
# New behavior with local thread separated results
|
||||||
$global:Icinga.CheckResults += $Output;
|
$global:Icinga.Private.Scheduler.CheckResults += $Output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,13 @@ function Write-IcingaPluginPerfData()
|
||||||
$PerformanceData = $PerformanceData.perfdata;
|
$PerformanceData = $PerformanceData.perfdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([string]::IsNullOrEmpty($CheckCommand) -eq $FALSE -And $Global:Icinga.ThresholdCache.ContainsKey($CheckCommand)) {
|
if ([string]::IsNullOrEmpty($CheckCommand) -eq $FALSE -And $Global:Icinga.Private.Scheduler.ThresholdCache.ContainsKey($CheckCommand)) {
|
||||||
$CheckResultCache = $Global:Icinga.ThresholdCache[$CheckCommand];
|
$CheckResultCache = $Global:Icinga.Private.Scheduler.ThresholdCache[$CheckCommand];
|
||||||
} else {
|
} else {
|
||||||
$CheckResultCache = New-Object PSCustomObject;
|
$CheckResultCache = New-Object PSCustomObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($global:IcingaDaemonData.FrameworkRunningAsDaemon -eq $FALSE -And $global:IcingaDaemonData.JEAContext -eq $FALSE) {
|
if ($Global:Icinga.Protected.RunAsDaemon -eq $FALSE -And $Global:Icinga.Protected.JEAContext -eq $FALSE) {
|
||||||
[string]$PerfDataOutput = (Get-IcingaPluginPerfDataContent -PerfData $PerformanceData -CheckResultCache $CheckResultCache -IcingaCheck $IcingaCheck);
|
[string]$PerfDataOutput = (Get-IcingaPluginPerfDataContent -PerfData $PerformanceData -CheckResultCache $CheckResultCache -IcingaCheck $IcingaCheck);
|
||||||
Write-IcingaConsolePlain ([string]::Format('| {0}', $PerfDataOutput));
|
Write-IcingaConsolePlain ([string]::Format('| {0}', $PerfDataOutput));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -60,7 +60,7 @@ function Get-IcingaPluginPerfDataContent()
|
||||||
|
|
||||||
if ($AsObject) {
|
if ($AsObject) {
|
||||||
# New behavior with local thread separated results
|
# New behavior with local thread separated results
|
||||||
$global:Icinga.PerfData += $cachedresult;
|
$global:Icinga.Private.Scheduler.PerformanceData += $cachedresult;
|
||||||
}
|
}
|
||||||
$PerfDataOutput += $cachedresult;
|
$PerfDataOutput += $cachedresult;
|
||||||
}
|
}
|
||||||
|
|
@ -70,7 +70,7 @@ function Get-IcingaPluginPerfDataContent()
|
||||||
|
|
||||||
if ($AsObject) {
|
if ($AsObject) {
|
||||||
# New behavior with local thread separated results
|
# New behavior with local thread separated results
|
||||||
$global:Icinga.PerfData += $compiledPerfData;
|
$global:Icinga.Private.Scheduler.PerformanceData += $compiledPerfData;
|
||||||
}
|
}
|
||||||
$PerfDataOutput += $compiledPerfData;
|
$PerfDataOutput += $compiledPerfData;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,8 +92,8 @@ function Convert-Base64ToCredentials()
|
||||||
|
|
||||||
$UserData = $null;
|
$UserData = $null;
|
||||||
} catch {
|
} catch {
|
||||||
Write-IcingaEventMessage -EventId 1552 -Namespace 'Framework' -Objects $_.Exception;
|
Write-IcingaEventMessage -EventId 1552 -Namespace 'Framework' -ExceptionObject $_;
|
||||||
return @{ };
|
return @{};
|
||||||
}
|
}
|
||||||
|
|
||||||
return $Credentials;
|
return $Credentials;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ function New-IcingaSSLStream()
|
||||||
$SSLStream = New-Object System.Net.Security.SslStream($Client.GetStream(), $false)
|
$SSLStream = New-Object System.Net.Security.SslStream($Client.GetStream(), $false)
|
||||||
$SSLStream.AuthenticateAsServer($Certificate, $false, [System.Security.Authentication.SslProtocols]::Tls12, $true) | Out-Null;
|
$SSLStream.AuthenticateAsServer($Certificate, $false, [System.Security.Authentication.SslProtocols]::Tls12, $true) | Out-Null;
|
||||||
} catch {
|
} catch {
|
||||||
Write-IcingaEventMessage -EventId 1500 -Namespace 'Framework' -Objects $Client.Client;
|
Write-IcingaEventMessage -EventId 1500 -Namespace 'Framework' -ExceptionObject $_ -Objects $Client.Client;
|
||||||
return $null;
|
return $null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ function Test-IcingaRESTCredentials()
|
||||||
);
|
);
|
||||||
} catch {
|
} catch {
|
||||||
# Regardless of the error, print the message and return false to prevent further execution
|
# Regardless of the error, print the message and return false to prevent further execution
|
||||||
Write-IcingaEventMessage -EventId 1560 -Namespace 'Framework' -Objects $_.Exception;
|
Write-IcingaEventMessage -EventId 1560 -Namespace 'Framework' -ExceptionObject $_;
|
||||||
return $FALSE;
|
return $FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,7 +71,7 @@ function Test-IcingaRESTCredentials()
|
||||||
|
|
||||||
return $AuthResult;
|
return $AuthResult;
|
||||||
} catch {
|
} catch {
|
||||||
Write-IcingaEventMessage -EventId 1561 -Namespace 'Framework' -Objects $_.Exception;
|
Write-IcingaEventMessage -EventId 1561 -Namespace 'Framework' -ExceptionObject $_;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $FALSE;
|
return $FALSE;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue