Remove remaining legacy code of module

This commit is contained in:
Lord Hepipud 2019-11-03 22:44:35 +01:00
parent 8e62cdb836
commit 6ffd3ac0ec
46 changed files with 0 additions and 4758 deletions

View file

@ -1,142 +0,0 @@
param(
[string]$AddKey = '',
[Object]$AddValue = '',
[string]$GetConfig = '',
[string]$RemoveConfig = '',
[boolean]$ListConfig = $FALSE,
[boolean]$Reload = $FALSE
);
function ClassConfig()
{
param(
[string]$AddKey = '',
[Object]$AddValue = '',
[string]$GetConfig = '',
[string]$RemoveConfig = '',
[boolean]$ListConfig = $FALSE,
[boolean]$Reload = $FALSE
);
$instance = New-Object -TypeName PSObject;
$instance | Add-Member -membertype NoteProperty -name 'ConfigDirectory' -value (Join-Path $Icinga2.App.RootPath -ChildPath 'agent\config');
$instance | Add-Member -membertype NoteProperty -name 'ConfigFile' -value (Join-Path $instance.ConfigDirectory -ChildPath 'config.conf');
$instance | Add-Member -membertype ScriptMethod -name 'Init' -value {
if ($ListConfig) {
return $this.DumpConfig();
}
if ($Reload) {
return $this.ReloadConfig();
}
if ([string]::IsNullOrEmpty($GetConfig) -eq $FALSE) {
return $this.GetAttribute();
}
if ([string]::IsNullOrEmpty($AddKey) -eq $FALSE) {
return $this.SetAttribute();
}
if ([string]::IsNullOrEmpty($RemoveConfig) -eq $FALSE) {
return $this.RemoveAttribute();
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
'{ Invalid or insufficient arguments specified. }'
);
return 1;
}
$instance | Add-Member -membertype ScriptMethod -name 'ReloadConfig' -value {
$Icinga2.Config = & (Join-Path $Icinga2.App.RootPath -ChildPath '\core\include\Config.ps1');
}
$instance | Add-Member -membertype ScriptMethod -name 'WriteConfig' -value {
If ((Test-Path ($this.ConfigDirectory)) -eq $FALSE) {
$Icinga2.Log.WriteConsole(
$Icinga2.Enums.LogState.Warning,
'Config Directory is not present. Please run "Icinga-Setup" for the base installation'
);
return 1;
}
$config = ConvertTo-Json $Icinga2.Config -Depth 100;
[System.IO.File]::WriteAllText($this.ConfigFile, $config);
return 0;
}
$instance | Add-Member -membertype ScriptMethod -name 'DumpConfig' -value {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
([string]::Format('Config location: {0}', $this.ConfigFile))
);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
$Icinga2.Config
);
return 0;
}
$instance | Add-Member -membertype ScriptMethod -name 'GetAttribute' -value {
return $Icinga2.Config.$GetConfig;
}
$instance | Add-Member -membertype ScriptMethod -name 'SetAttribute' -value {
$value = $AddValue;
if ([string]::IsNullOrEmpty($AddValue)) {
$value = $null;
}
if ([bool]($Icinga2.Config.PSobject.Properties.Name -eq $AddKey) -eq $FALSE) {
$Icinga2.Config | Add-Member -membertype NoteProperty -name $AddKey -value $value;
} else {
$Icinga2.Config.$AddKey = $value;
}
if ($this.WriteConfig() -eq 0) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
([string]::Format('{0} Set config attribute "{1}" to "{2}. {3}', '{', $AddKey, $value, '}'))
);
return 0;
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Error,
([string]::Format('{0} Unable to write config file to disk. Failed to update attribute "{1}" to "{2}. {3}', '{', $AddKey, $value, '}'))
);
return 1;
}
$instance | Add-Member -membertype ScriptMethod -name 'RemoveAttribute' -value {
if ([bool]($Icinga2.Config.PSobject.Properties.Name -eq $RemoveConfig) -eq $TRUE) {
$Icinga2.Config.PSobject.Members.Remove($RemoveConfig);
if ($this.WriteConfig() -eq 0) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
([string]::Format('{0} Successfully removed config attribute "{1}" {2}', '{', $RemoveConfig, '}'))
);
return 0;
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Error,
([string]::Format('{0} Config attribute "{1}" was removed, but storing the new config file failed. {2}', '{', $RemoveConfig, '}'))
);
return 1;
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Warning,
([string]::Format('{0} Unable to remove attribute "{1}". Attribute not found {2}', '{', $RemoveConfig, '}'))
);
return 1;
}
return $instance.Init();
}
return ClassConfig -AddKey $AddKey -AddValue $AddValue -GetConfig $GetConfig -RemoveConfig $RemoveConfig -ListConfig $ListConfig -Reload $Reload;

View file

@ -1,100 +0,0 @@
$APIResponse = New-Object -TypeName PSObject;
$APIResponse | Add-Member -membertype NoteProperty -name 'static' -value $FALSE;
$APIResponse | Add-Member -membertype NoteProperty -name 'statuscode' -value 200;
$APIResponse | Add-Member -membertype NoteProperty -name 'message' -value '';
$APIResponse | Add-Member -membertype NoteProperty -name 'content' -value $null;
$APIResponse | Add-Member -membertype NoteProperty -name 'authheader' -value '';
$APIResponse | Add-Member -membertype ScriptMethod -name 'setContent' -value {
param([object]$content);
$this.content = $content;
}
$APIResponse | Add-Member -membertype ScriptMethod -name 'CustomBadRequest' -value {
param([string]$message);
$this.statuscode = 400;
$this.message = $message;
}
$APIResponse | Add-Member -membertype ScriptMethod -name 'InternalServerError' -value {
$this.statuscode = 500;
$this.message = 'An internal server error occured while parsing your request.';
}
$APIResponse | Add-Member -membertype ScriptMethod -name 'HTTPSRequired' -value {
$this.statuscode = 403;
$this.message = 'This API only supports connections over HTTPS.';
}
$APIResponse | Add-Member -membertype ScriptMethod -name 'AuthenticationRequired' -value {
$this.statuscode = 401;
$this.message = 'You require to login in order to access this ressource.';
$this.authheader = [string]::Format(
'WWW-Authenticate: Basic realm="Icinga Windows Daemon"{0}',
"`r`n"
);
}
$APIResponse | Add-Member -membertype ScriptMethod -name 'CompileMessage' -value {
# If our message is empty, do nothing
if ([string]::IsNullOrEmpty($this.message)) {
return;
}
# In case we assigned custom content, do not override this content
if ($this.content -ne $null) {
return;
}
$this.content = @{
response = $this.statuscode;
message = $this.message;
};
}
$APIResponse | Add-Member -membertype ScriptMethod -name 'Compile' -value {
$this.CompileMessage();
[string]$ContentLength = '';
[string]$HTMLContent = '';
if ($this.content -ne $null) {
$json = ConvertTo-Json $this.content -Depth 100 -Compress;
$bytes = [System.Text.Encoding]::UTF8.GetBytes($json);
$HTMLContent = [System.Text.Encoding]::UTF8.GetString($bytes);
if ($bytes.Length -gt 0) {
$ContentLength = [string]::Format(
'Content-Length: {0}{1}',
$bytes.Length,
"`r`n"
);
}
}
return -Join(
[string]::Format(
'HTTP/1.1 {0} {1}{2}',
$this.statuscode,
$Icinga2.Enums.HttpStatusCodes.$this.statuscode,
"`r`n"
),
[string]::Format(
'Server: {0}{1}',
(Get-WmiObject Win32_ComputerSystem).Name,
"`r`n"
),
[string]::Format(
'Content-Type: application/json{0}',
"`r`n"
),
$this.authheader,
$ContentLength,
"`r`n",
$HTMLContent
);
}
return $APIResponse;

View file

@ -1,15 +0,0 @@
# App configuration
$App = @{
LogSeverity = [PSCustomObject]@{
PSTypeName = "LogSeverity"
Info = 0
Warning = 1
Error = 2
Exception = 3
Debug = 4
};
RootPath = $_InternalTempVariables.RootPath;
ModuleName = $_InternalTempVariables.ModuleName;
}
return $App;

View file

@ -1,105 +0,0 @@
$Checker = New-Object -TypeName PSObject;
$Checker | Add-Member -membertype NoteProperty -name 'os' -value '';
$Checker | Add-Member -membertype NoteProperty -name 'version' -value '';
$Checker | Add-Member -membertype NoteProperty -name 'fqdn' -value '';
$Checker | Add-Member -membertype NoteProperty -name 'bind' -value 'wdt';
$Checker | Add-Member -membertype NoteProperty -name 'time_offset' -value 0;
$Checker | Add-Member -membertype ScriptMethod -name 'Start' -value {
$Icinga2.PidManager.StopProcessByBind($this.bind);
Start-Sleep 1;
$Icinga2.PidManager.CreatePidFile($this.bind);
$WindowsInformations = Get-CimInstance Win32_OperatingSystem;
$this.version = $WindowsInformations.CimInstanceProperties['Version'].Value;
$this.os = $WindowsInformations.CimInstanceProperties['Caption'].Value;
$this.fqdn = [System.Net.Dns]::GetHostEntry('localhost').HostName;
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
'Starting checker component of module.'
);
$Icinga2.ClientProtocol.setFQDN($this.fqdn);
$Icinga2.Cache.Checker.ModuleScheduler = @{ };
while($true) {
$StopWatchHandler = [System.Diagnostics.StopWatch]::StartNew()
$this.ScheduleWindowsHello($FALSE);
$this.UpdateModuleTimer();
$Icinga2.ClientJobs.ParseJobResults();
# This part will help us to keep the gap between module execution as low as possible
# We will check how many seconds have been passed while the modules were executed
# This value will then be added to our module timings, ensuring that in general
# they will become executed right on time
$StopWatchHandler.Stop();
$this.time_offset = [math]::Round($StopWatchHandler.Elapsed.TotalSeconds, 0);
$Icinga2.ClientJobs.AddTicks($this.time_offset);
Start-Sleep -Seconds 1;
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
'Stopping checker component of module.'
);
}
$Checker | Add-Member -membertype ScriptMethod -name 'UpdateModuleTimer' -value {
if ($Icinga2.Cache.Checker.ModuleConfig -eq $null) {
return;
}
foreach ($module in $Icinga2.Cache.Checker.ModuleConfig.Keys) {
if ($Icinga2.Cache.Checker.ModuleScheduler.ContainsKey($module) -eq $FALSE) {
$Icinga2.Cache.Checker.ModuleScheduler.Add($module, 0);
} else {
$Icinga2.Cache.Checker.ModuleScheduler[$module] += (1 + $this.time_offset);
if ($Icinga2.Cache.Checker.ModuleScheduler[$module] -ge $Icinga2.Cache.Checker.ModuleConfig[$module]) {
$Icinga2.Cache.Checker.ModuleScheduler[$module] = 0;
$this.ScheduleModuleJob($module);
}
}
}
$this.time_offset = 0;
}
$Checker | Add-Member -membertype ScriptMethod -name 'ScheduleModuleJob' -value {
param([string]$module);
$Icinga2.ClientJobs.ScheduleJob($module);
}
$Checker | Add-Member -membertype ScriptMethod -name 'ScheduleWindowsHello' -value {
param([bool]$force);
$this.WriteLogOutput($Icinga2.ClientJobs.WindowsHello(
$this.os,
$this.fqdn,
$this.version,
$force
));
}
$Checker | Add-Member -membertype ScriptMethod -name 'WriteLogOutput' -value {
param($response);
if ($response -ne $null) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
$response
);
}
}
$Checker | Add-Member -membertype ScriptMethod -name 'Stop' -value {
$Icinga2.PidManager.StopProcessByBind($this.bind);
}
return $Checker;

View file

@ -1,292 +0,0 @@
$ClientJobs = New-Object -TypeName PSObject;
$ClientJobs | Add-Member -membertype NoteProperty -name 'hello_counter' -value 0;
$ClientJobs | Add-Member -membertype NoteProperty -name 'module_scheduler' -value @( );
$ClientJobs | Add-Member -membertype NoteProperty -name 'module_output' -value $null;
$ClientJobs | Add-Member -membertype ScriptMethod -name 'AddTicks' -value {
param([int]$ticks);
$this.hello_counter += $ticks;
}
$ClientJobs | Add-Member -membertype ScriptMethod -name 'WindowsHello' -value {
param([string]$os, [string]$fqdn, [string]$version, [bool]$force);
if ($this.hello_counter -ge 30) {
$this.hello_counter = 0;
}
if ($this.hello_counter -eq 0 -Or $force -eq $TRUE) {
[hashtable]$hello = @{
'os' = $os;
'fqdn' = $fqdn;
'version' = $version;
'port' = $Icinga2.Config.'tcp.socket.port';
};
[string]$token = $this.getAuthToken();
if ([string]::isNullOrEmpty($token) -eq $FALSE) {
$hello.Add(
'modules',
(New-Icinga-Monitoring -ListModules)
)
}
$response = $Icinga2.ClientProtocol.NewRequest(
@('X-Windows-Hello: 1'),
($hello | ConvertTo-Json -Depth 2 -Compress),
$Icinga2.Config.'checker.server.host',
$token
);
$this.hello_counter += 1;
if ($response -eq $null) {
return $null;
}
try {
$json = $response | ConvertFrom-Json;
$Icinga2.Cache.Checker.Authenticated = $TRUE;
$Icinga2.ClientProtocol.parseWindowsHelloResponse($json);
return $null;
} catch {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
$_.Exception.Message
);
}
$Icinga2.Cache.Checker.Authenticated = $FALSE;
return $response;
}
$this.hello_counter += 1;
return $null;
}
$ClientJobs | Add-Member -membertype ScriptMethod -name 'getAuthToken' -value {
[string]$token = '';
if ($Icinga2.Cache.Checker.Authenticated -eq $TRUE -And $Icinga2.Cache.Checker.AuthToken -ne $null) {
$token = [string]::Format('?token={0}', $Icinga2.Cache.Checker.AuthToken);
}
return $token;
}
$ClientJobs | Add-Member -membertype ScriptMethod -name 'ScheduleJob' -value {
param([string]$module);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format(
'Scheduling execution check for module: {0}',
$module
)
);
$this.module_scheduler += $module;
return;
# This would be the best, but will cause too much overhead and system load
Start-Job -Name $module -ScriptBlock {
return New-Icinga-Monitoring -include $args[0];
} -ArgumentList $module;
}
$ClientJobs | Add-Member -membertype ScriptMethod -name 'ParseJobResults' -value {
if ($this.module_scheduler.Count -eq 0) {
return;
}
$moduleOutput = New-Icinga-Monitoring -Include ($this.module_scheduler) -Config $Icinga2.Cache.Checker.ModuleArguments;
[string]$token = $this.getAuthToken();
[string]$modules = $this.module_scheduler -Join ","
if ([string]::isNullOrEmpty($token) -eq $TRUE) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
'Unable to send job results to server. No auth token is specified'
);
$this.FlushModuleCache($TRUE);
return;
}
if ($Icinga2.ClientProtocol.GetConnectionState($Icinga2.Config.'checker.server.host') -eq $FALSE) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Warning,
[string]::Format(
'Module results for "{0}" will not be send to {1}. A previous connection failed. Re-Trying in some seconds...',
$modules,
$Icinga2.Config.'checker.server.host'
)
);
$this.FlushModuleCache($TRUE);
return;
}
$this.module_output = ($moduleOutput | ConvertTo-Json -Depth 100 -Compress);
$response = $Icinga2.ClientProtocol.NewRequest(
@('X-Windows-Result: 1'),
$this.module_output,
$Icinga2.Config.'checker.server.host',
[string]::Format(
'{0}&results=1',
$token
)
);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format(
'Send modules {0} results to server. Received result: {1}',
$modules,
$response
)
);
$this.ParseResponse($response);
return;
# This would be the best, but will cause too much overhead and system load
[hashtable]$moduleOutput = @{ };
Get-Job -State Completed | Where-Object {
$moduleOutput.Add(
$_.Name,
(Receive-Job -Id $_.Id)
);
Remove-Job -Id $_.Id;
};
[string]$token = $this.getAuthToken();
if ([string]::isNullOrEmpty($token) -eq $TRUE) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
'Unable to send job results to server. No auth token is specified'
);
return;
}
if ($Icinga2.ClientProtocol.GetConnectionState($Icinga2.Config.'checker.server.host') -eq $FALSE) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Warning,
[string]::Format(
'Module results for "{0}" will not be send to {1}. A previous connection failed. Re-Trying in some seconds...',
$modules,
$Icinga2.Config.'checker.server.host'
)
);
return;
}
$response = $Icinga2.ClientProtocol.NewRequest(
@('X-Windows-Result: 1'),
($moduleOutput | ConvertTo-Json -Depth 100 -Compress),
$Icinga2.Config.'checker.server.host',
[string]::Format(
'{0}&results=1',
$token
)
);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format(
'Send modules {0} results to server. Received result: {1}',
($moduleOutput | Out-String),
$response
)
);
}
$ClientJobs | Add-Member -membertype ScriptMethod -name 'FlushModuleCache' -value {
param([bool]$flush);
if ($flush -eq $TRUE) {
foreach($module in $this.module_scheduler) {
$Icinga2.Utils.Modules.FlushModuleCache($module);
}
}
$this.module_scheduler = @();
}
$ClientJobs | Add-Member -membertype ScriptMethod -name 'ParseResponse' -value {
param([string]$response);
if ([string]::IsNullOrEmpty($response) -eq $TRUE) {
$this.FlushModuleCache($TRUE);
return;
}
# Re-Try to send the informations once in case we are not authorized
if ($response -eq '401') {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Warning,
'Received Unauthorized (401) response. Trying to re-send results after requesting permission.'
);
$Icinga2.Checker.ScheduleWindowsHello($TRUE);
[string]$token = $this.getAuthToken();
$response = $Icinga2.ClientProtocol.NewRequest(
@('X-Windows-Result: 1'),
$this.module_output,
$Icinga2.Config.'checker.server.host',
[string]::Format(
'{0}&results=1',
$token
)
);
if ([string]::IsNullOrEmpty($response) -eq $TRUE) {
$this.FlushModuleCache($TRUE);
return;
}
}
try {
$json = ConvertFrom-Json $response -ErrorAction Stop -WarningAction Stop;
} catch {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Error,
[string]::Format(
'Received invalid JSON response from request: {0}',
$response
)
);
$this.FlushModuleCache($TRUE);
return;
}
try {
if ($json.response -ne $null) {
if ($json.response -ne 200) {
$this.FlushModuleCache($TRUE);
return;
}
}
} catch {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Error,
[string]::Format(
'Failed to properly parse JSON response: {0} . Exception Message: {1}',
$response,
$_.Exception.Message
)
);
$this.FlushModuleCache($TRUE);
return;
}
$this.FlushModuleCache($FALSE);
}
return $ClientJobs;

View file

@ -1,225 +0,0 @@
$ClientProtocol = New-Object -TypeName PSObject;
$ClientProtocol | Add-Member -membertype NoteProperty -name 'fqdn' -value '';
$ClientProtocol | Add-Member -membertype ScriptMethod -name 'setFQDN' -value {
param([string]$fqdn);
$this.fqdn = $fqdn;
}
$ClientProtocol | Add-Member -membertype ScriptMethod -name 'SetConnectionState' -value {
param([string]$remoteAddress, [bool]$reachable);
if ($Icinga2.Cache.Checker.RemoteServices -eq $null) {
$Icinga2.Cache.Checker.RemoteServices = @{ };
}
if ($Icinga2.Cache.Checker.RemoteServices.ContainsKey($remoteAddress) -eq $FALSE) {
$Icinga2.Cache.Checker.RemoteServices.Add($remoteAddress, $reachable);
return;
}
$Icinga2.Cache.Checker.RemoteServices[$remoteAddress] = $reachable;
}
$ClientProtocol | Add-Member -membertype ScriptMethod -name 'GetConnectionState' -value {
param([string]$remoteAddress);
if ($Icinga2.Cache.Checker.RemoteServices.ContainsKey($remoteAddress) -eq $FALSE) {
return $TRUE;
}
return $Icinga2.Cache.Checker.RemoteServices[$remoteAddress];
}
$ClientProtocol | Add-Member -membertype ScriptMethod -name 'NewRequest' -value {
param([array]$headers, [string]$content, [string]$remoteAddress, [string]$url);
$url = [string]::Format(
'{0}{1}',
$remoteAddress,
$url
);
$httpRequest = [System.Net.HttpWebRequest]::Create(
$url
);
$httpRequest.Method = 'POST';
$httpRequest.Accept = 'application/json';
$httpRequest.ContentType = 'application/json';
$httpRequest.Headers.Add(
[string]::Format(
'X-Windows-CheckResult: {0}',
$this.fqdn
)
);
# Add possible custom header
foreach ($header in $headers) {
$httpRequest.Headers.Add($header);
}
$httpRequest.TimeOut = 60000;
# If we are using self-signed certificates for example, the HTTP request will
# fail caused by the SSL certificate. With this we can allow even faulty
# certificates. This should be used with caution
if (-Not $Icinga2.Config.'checker.ssl.verify') {
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
}
try {
# Only send data in case we want to send some data
if ($content -ne '') {
$transmitBytes = [System.Text.Encoding]::UTF8.GetBytes($content);
$httpRequest.ContentLength = $transmitBytes.Length;
[System.IO.Stream]$httpOutput = [System.IO.Stream]$httpRequest.GetRequestStream()
$httpOutput.Write($transmitBytes, 0, $transmitBytes.Length)
$httpOutput.Close()
}
} catch [System.Net.WebException] {
$this.SetConnectionState($remoteAddress, $FALSE);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
[string]::Format('Exception while trying to connect to "{0}". Possible a connection error. Message: {1}',
$url,
$_.Exception.Message
)
);
return $null;
} catch {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
$_.Exception.Message
);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
$_.Exception.StackTrace
);
return $null;
}
try {
$this.SetConnectionState($remoteAddress, $TRUE);
return $this.readResponseStream($httpRequest.GetResponse());
} catch [System.Net.WebException] {
# Print an exception message and the possible body in case we received one
# to make troubleshooting easier
[string]$errorResponse = $this.readResponseStream($_.Exception.Response);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
$_.Exception.Message
);
if ($errorResponse -ne '') {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
$errorResponse
);
}
$exceptionMessage = $_.Exception.Response;
if ($exceptionMessage.StatusCode) {
return [int][System.Net.HttpStatusCode]$exceptionMessage.StatusCode;
} else {
return 900;
}
}
return $null;
}
$ClientProtocol | Add-Member -membertype ScriptMethod -name 'readResponseStream' -value {
param([System.Object]$response);
try {
if ($response) {
$responseStream = $response.getResponseStream();
$streamReader = New-Object IO.StreamReader($responseStream);
$result = $streamReader.ReadToEnd();
$response.close()
$streamReader.close()
return $result;
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
'The received response from the remote server is NULL. This might be caused by SSL errors or wrong Webserver configuration.'
);
} catch {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
$_.Exception.Message
);
}
return $null;
}
$ClientProtocol | Add-Member -membertype ScriptMethod -name 'parseWindowsHelloResponse' -value {
param($json);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format(
'Remote Server Output: {0}',
$json
)
);
$Icinga2.Cache.Checker.AuthToken = $json.token;
if ($Icinga2.Cache.Checker.ModuleConfig -eq $null) {
$Icinga2.Cache.Checker.ModuleConfig = @{};
}
$Icinga2.Cache.Checker.ModuleArguments = $json.module_arguments;
[hashtable]$activeModules = @{};
foreach ($module in $json.modules) {
if ($Icinga2.Cache.Checker.ModuleConfig.ContainsKey($module.name)) {
$Icinga2.Cache.Checker.ModuleConfig[$module.name] = $module.check_interval;
} else {
$Icinga2.Cache.Checker.ModuleConfig.Add($module.name, $module.check_interval);
}
$activeModules.Add($module.name, $TRUE);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format(
'Adding module {0} with check intervall {1}',
$module.name,
$module.check_interval
)
);
}
# We might have disabled some modules. Lets handle this by setting the
# execution timer to -1
foreach ($module in $Icinga2.Cache.Checker.ModuleConfig.Keys) {
if ($activeModules.ContainsKey($module) -eq $FALSE) {
$activeModules.Add($module, $FALSE);
}
}
# We require a second loop to ensure we won't crash because of a changed hashtable
foreach($module in $activeModules.Keys) {
if ($activeModules[$module] -eq $FALSE) {
if ($Icinga2.Cache.Checker.ModuleConfig.ContainsKey($module)) {
$Icinga2.Cache.Checker.ModuleConfig.Remove($module);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format(
'Disabling module {0}',
$module
)
);
}
}
}
}
return $ClientProtocol;

View file

@ -1,24 +0,0 @@
# Inetrnal variable to store the root directory path
[string]$RootDirectory = '';
# In case we load the module for the first time, this variable contains the root path
# of our module
if ($_InternalTempVariables -ne $null) {
$RootDirectory = $_InternalTempVariables.RootPath;
} else {
# In case we want to reload the configuration, we simply can access the namespace
# variable we already loaded
$RootDirectory = $Icinga2.App.RootPath;
}
# Build the Config directory and file path
[string]$ConfigDirectory = (Join-Path $RootDirectory -ChildPath 'agent\config');
[string]$ConfigFile = (Join-Path $ConfigDirectory -ChildPath 'config.conf');
# In case the config file does not exist, return an empty hashtable
if ((Test-Path ($ConfigFile)) -eq $FALSE) {
return ('{ }' | ConvertFrom-Json);
}
# Return the content of the file as objects (config is stored as JSON)
return ([System.IO.File]::ReadAllText($ConfigFile) | ConvertFrom-Json);

View file

@ -1,83 +0,0 @@
<#
# This script will provide 'Enums' we can use within our module to
# easier access constants and to maintain a better overview of the
# entire components
#>
[hashtable]$LogState = @{
Info = 0;
Warning = 1;
Error = 2;
Exception = 3;
Debug = 4;
};
[hashtable]$LogSeverity = @{
0 = 'Info';
1 = 'Warning';
2 = 'Error';
3 = 'Exception';
4 = 'Debug';
};
[hashtable]$EventLogType = @{
0 = 'Information';
1 = 'Warning';
2 = 'Error';
3 = 'Error';
4 = 'Information';
};
[hashtable]$LogColor = @{
0 = 'DarkGreen';
1 = 'Yellow';
2 = 'Red';
3 = 'DarkRed';
4 = 'Magenta';
};
[hashtable]$ServiceStatus = @{
'NotInstalled' = 'The Icinga service for this module is not installed. Please run Install-Icinga to install the service.';
'Running' = 'The Icinga service is running.';
'Stopped' = 'The Icinga service is not running.';
'Starting' = 'The Icinga service is about to start.';
'Stopping' = 'The Icinga service is shutting down.';
}
[hashtable]$SCErrorCodes = @{
5 = 'Failed to execute Icinga 2 Service operation: Permission denied.';
1053 = 'Failed to start the Icinga 2 Service: The Service did not respond in time to the start or operation request.';
1056 = 'Failed to start the Icinga 2 Service: The Service is already running.';
1060 = 'Failed to apply action for Icinga 2 Service: The Service is not installed.';
1062 = 'Failed to stop the Icinga 2 Service: The Service is not running.';
1072 = 'Failed to uninstall the Icinga 2 Service: The Service is already marked for deletion.';
1073 = 'Failed to install the Icinga 2 Service: The Service is already installed.';
};
[hashtable]$HttpStatusCodes = @{
200 = 'Ok';
400 = 'Bad Request';
401 = 'Unauthorized';
403 = 'Forbidden';
404 = 'Not Found'
500 = 'Internal Server Error';
};
<#
# Once we defined a new enum hashtable above, simply add it to this list
# to make it available within the entire module.
#
# Example usage:
# $Icinga2.Enums.LogState.Info
#>
[hashtable]$Enums = @{
LogSeverity = $LogSeverity;
EventLogType = $EventLogType;
LogColor = $LogColor;
LogState = $LogState;
ServiceStatus = $ServiceStatus;
SCErrorCodes = $SCErrorCodes;
HttpStatusCodes = $HttpStatusCodes;
}
return $Enums;

View file

@ -1,128 +0,0 @@
<#
# Handle the entire logging process of the module by sending the events
# to console, the event log and if configured into an own log file.
# This entire script will return a 'function' handler, dealing with
# all events.
# To create log events, simply use the following example:
#
# $Icinga2.Log.Write($Icinga2.Enums.LogState.Info, 'This is a info message');
#>
$IcingaLogger = New-Object -TypeName PSObject;
$IcingaLogger | Add-Member -membertype NoteProperty -name 'noconsole' -value $FALSE;
$IcingaLogger | Add-Member -membertype ScriptMethod -name 'DisableConsole' -value {
$this.noconsole = $TRUE;
}
$IcingaLogger | Add-Member -membertype ScriptMethod -name 'Write' -value {
param($Severity, [string]$Message);
# Only write debug output if enabled
if ($Severity -eq $Icinga2.Enums.LogState.Debug -And $Icinga2.Config.'logger.debug' -eq $FALSE) {
return;
}
[string]$SeverityToString = $this.GetSeverityAsString($Severity);
# Format a timestamp to get to know the exact date and time. Example: 2017-13-07 22:09:13.263.263
$timestamp = Get-Date -Format "yyyy-dd-MM HH:mm:ss.fff";
[string]$LogMessage = [string]::Format('{0} [{1}]: {2}', $timestamp, $SeverityToString, $Message);
$this.WriteConsole($Severity, $LogMessage);
$this.WriteEventLog($Severity, $Message);
$this.WriteLogFile($Severity, $LogMessage);
}
$IcingaLogger | Add-Member -membertype ScriptMethod -name 'GetConsoleColorFromSeverity' -value {
param([int]$Severity);
if ($Icinga2.Enums.LogColor.ContainsKey($Severity) -eq $FALSE) {
return 'White';
}
return $Icinga2.Enums.LogColor[$Severity];
}
$IcingaLogger | Add-Member -membertype ScriptMethod -name 'GetSeverityAsString' -value {
param([int]$Severity);
if ($Icinga2.Enums.LogSeverity.ContainsKey($Severity) -eq $FALSE) {
return 'Undefined';
}
return $Icinga2.Enums.LogSeverity[$Severity];
}
$IcingaLogger | Add-Member -membertype ScriptMethod -name 'WriteLogFile' -value {
param([int]$Severity, [string]$Message);
[string]$LogDirectory = $Icinga2.Config.'logger.directory';
if ([string]::IsNullOrEmpty($LogDirectory)) {
return;
}
if (-Not (Test-Path $LogDirectory)) {
New-Item $LogDirectory -ItemType Directory | Out-Null;
# Something went wrong while trying to create the directory
if (-Not (Test-Path $LogDirectory)) {
$this.WriteConsole($Icinga2.Enums.LogState.Error,
[string]::Format('Failed to create logfile directory at location "{0}"', $LogDirectory)
)
return;
}
}
[string]$LogFile = Join-Path $LogDirectory -ChildPath 'icinga2.log';
try {
$LogStream = New-Object System.IO.FileStream(
$LogFile,
[System.IO.FileMode]::Append,
[System.IO.FileAccess]::Write,
[IO.FileShare]::Read
);
$LogWriter = New-Object System.IO.StreamWriter($LogStream);
$LogWriter.writeLine($Message);
} catch {
$this.WriteConsole($Icinga2.Enums.LogState.Error,
[string]::Format('Failed to write into logfile: "{0}"', $_.Exception.Message)
)
} finally {
$LogWriter.Dispose();
}
}
$IcingaLogger | Add-Member -membertype ScriptMethod -name 'WriteEventLog' -value {
param([int]$Severity, [string]$Message);
try {
Write-EventLog -LogName "Application" `
-Source $Icinga2.Service.servicedisplayname `
-EventID (1000 + $Severity) `
-EntryType $Icinga2.Enums.EventLogType.$Severity `
-Message $Message `
-Category $Severity `
-ErrorAction Stop;
} catch {
$this.WriteLogFile(
$Icinga2.Enums.LogState.Error,
$_.Exception.Message
);
}
}
$IcingaLogger | Add-Member -membertype ScriptMethod -name 'WriteConsole' -value {
param([int]$Severity, [string]$Message);
if ($this.noconsole) {
return;
}
Write-Host $Message -ForegroundColor ($this.GetConsoleColorFromSeverity($Severity))
}
return $IcingaLogger;

View file

@ -1,192 +0,0 @@
$NetworkProtocol = New-Object -TypeName PSObject;
$NetworkProtocol | Add-Member -membertype NoteProperty -name 'static' -value $FALSE;
$NetworkProtocol | Add-Member -membertype NoteProperty -name 'sslstream' -value $null;
$NetworkProtocol | Add-Member -membertype NoteProperty -name 'networkstream' -value $null;
$NetworkProtocol | Add-Member -membertype NoteProperty -name 'encrypted' -value $null;
$NetworkProtocol | Add-Member -membertype ScriptMethod -name 'Create' -value {
param($Stream);
$this.networkstream = $Stream;
$this.sslstream = $this.CreateSSLStream($Stream);
}
$NetworkProtocol | Add-Member -membertype ScriptMethod -name 'CreateSSLStream' -value {
param($Stream);
try {
$sslStream = New-Object System.Net.Security.SslStream(
$Stream,
$false
)
$sslStream.AuthenticateAsServer(
$Icinga2.Cache.Certificates.Server,
0,
[System.Security.Authentication.SslProtocols]::Tls,
1
);
$sslStream.ReadTimeout = 2000;
$this.encrypted = $TRUE;
return $sslStream;
} catch [System.IO.IOException] {
# Exceptions which occure when connecting from HTTP to this API, as we force HTTPS
# Use the client's non-ssl stream to inform the user about our forced
# HTTPS handling and set an internal variable to not send any data
# to our client over HTTP
$this.encrypted = $FALSE;
$Stream.ReadTimeout = 2000;
$Stream.WriteTimeout = 2000;
return $Stream;
} catch [System.NotSupportedException] {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
'The used SSL certificate is not providing a linked private key and cannot be used as Server certificate'
);
} catch {
# Handle every other error here
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
$_.Exception.Message
);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
$_.Exception
);
}
return $null;
}
$NetworkProtocol | Add-Member -membertype ScriptMethod -name 'ReadMessage' -value {
param([int]$BytesToRead)
# If we have no bytes to read, do nothing
if ($BytesToRead -eq 0) {
return $null;
}
[string]$content = '';
[SecureString]$SecureContent = $null;
[int]$TotalMessageSize = 0;
# Define our buffer size to ensure we read a certain
# amount of bytes each read attempt only
[int]$BufferSize = 1024;
# If we read the message and don't know if there is a content available
# we have to read until we reach EOF. In case we have the exact size
# of the content, we can read the possible rest
[bool]$IsSizeKnown = $FALSE;
# This will allow us to read a fixed amount of data from our
# stream and terminate the operation afterwards
if ($BytesToRead -gt 0) {
$BufferSize = $BytesToRead;
$IsSizeKnown = $TRUE;
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
'Reading new message from TCP NetworkStream of Client'
);
# Handle errors while reading the SSL Stream
try {
# Read the stream as long as we receive data from it
while ($true) {
# Create a new byte array with a fixed buffer size
[byte[]]$bytes = New-Object byte[] $BufferSize;
# Read the actual data from the stream
$bytesRead = $this.sslstream.Read($bytes, 0, $bytes.Length);
$TotalMessageSize += $bytesRead;
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format(
'Reading {0} bytes from TCP connection',
$bytesRead
)
);
# Build a output message from our received as string and perform
# possible required cleanup in addition
if ($bytesRead -ne 0) {
[string]$message = [System.Text.Encoding]::UTF8.GetString($bytes);
# In case we receive a larger message, append the message content
# to our string value
$content = -Join(
$content,
$message
);
# Ensure our output string is always matching the correct length
# but only apply this in case we are unsure about the real length
if ($IsSizeKnown -eq $FALSE) {
$content = $content.Substring(
0,
$TotalMessageSize
);
}
# EOF reached or the amount of bytes to read was known
# and we should abort here
if ($content.Contains("`r`n`r`n") -Or $IsSizeKnown) {
break;
}
} else {
break;
}
}
} catch {
# Might be good too remove this, as errors will occure very likely in case the SSLStream
# timed out after 2 seconds because no new data have been received.
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
[string]::Format(
'Failed to read Message from stream: {0}',
$_.Exception.Message
)
);
return $null;
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format(
'Finished reading {0} bytes from current NetworkMessage',
$TotalMessageSize
)
);
# In case we read no message from the stream, we should do nothing
if ($TotalMessageSize -eq 0) {
return $null;
}
$SecureContent = $Icinga2.Utils.SecureString.ConvertTo($content);
$content = $null;
return $SecureContent;
}
$NetworkProtocol | Add-Member -membertype ScriptMethod -name 'WriteMessage' -value {
param($message);
try {
$bytes = [System.Text.Encoding]::UTF8.GetBytes($message);
$Client.SendBufferSize = $bytes.Length;
$this.sslstream.Write($bytes, 0, $bytes.Length);
$this.sslstream.Flush();
} catch {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
'Failed to write message into data stream'
);
}
}
return $NetworkProtocol;

View file

@ -1,149 +0,0 @@
$PidManager = New-Object -TypeName PSObject;
$PidManager | Add-Member -membertype ScriptMethod -name 'PidExists' -value {
param([string]$bind);
[string]$PidFile = $this.PidFileName($bind);
return (Test-Path ($this.FullPidPath($PidFile)));
}
$PidManager | Add-Member -membertype ScriptMethod -name 'CreatePidFile' -value {
param([string]$bind);
[string]$PidFile = $this.PidFileName($bind);
Add-Content -Path ($this.FullPidPath($PidFile)) -Value $pid;
}
$PidManager | Add-Member -membertype ScriptMethod -name 'PidFileName' -value {
param([string]$bind);
return [string]::Format(
'icingabind{0}.pid',
$bind
);
}
$PidManager | Add-Member -membertype ScriptMethod -name 'FullPidPath' -value {
param([string]$PidFile);
return (Join-Path $Icinga2.App.RootPath -ChildPath (
[string]::Format(
'\agent\state\{0}',
$PidFile
)
));
}
$PidManager | Add-Member -membertype ScriptMethod -name 'ProcessID' -value {
param([string]$FullPidFile);
if ((Test-Path $FullPidFile) -eq $FALSE) {
return 0;
}
return Get-Content -Path $FullPidFile;
}
$PidManager | Add-Member -membertype ScriptMethod -name 'GetPIDByBind' -value {
param([string]$bind);
return $this.ProcessID(
$this.FullPidPath(
$this.PidFileName(
$bind
)
)
);
}
$PidManager | Add-Member -membertype ScriptMethod -name 'GetPIDPathByBind' -value {
param([string]$bind);
return $this.FullPidPath(
$this.PidFileName(
$bind
)
);
}
$PidManager | Add-Member -membertype ScriptMethod -name 'RemovePidFile' -value {
param([string]$FullPidPath, [string]$bind);
[string]$PidFile = $this.PidFileName($bind);
if (Test-Path $FullPidPath) {
Remove-Item $FullPidPath | Out-Null;
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
[string]::Format(
'Removing PID-File "{0}" for bind "{1}"',
$PidFile,
$bind
)
);
} else {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Warning,
[string]::Format(
'PID File "{0}" for bind "{1}" does not exist and could therefor not be removed',
$PidFile,
$bind
)
);
}
}
$PidManager | Add-Member -membertype ScriptMethod -name 'PidProcess' -value {
param([int]$ProcessID);
if ($ProcessID -eq 0) {
return $null;
}
# Look for the Process over WMI, as we might run as Service User and require
# to fetch the entire scope of running processes
$ProcessList = Get-WmiObject Win32_Process | Select-Object ProcessName, ProcessId -ErrorAction Stop;
foreach ($process in $ProcessList) {
if ($process.ProcessId -eq $ProcessID) {
if ($process.ProcessName -eq 'powershell.exe') {
return $process;
}
}
}
return $null;
}
$PidManager | Add-Member -membertype ScriptMethod -name 'StopProcessByBind' -value {
param([string]$bind);
if ($this.PidExists($bind)) {
$ProcessId = $this.GetPIDByBind($bind);
$this.ShutdownProcess($ProcessId);
$this.RemovePidFile(
$this.GetPIDPathByBind($bind),
$bind
);
}
}
$PidManager | Add-Member -membertype ScriptMethod -name 'ShutdownProcess' -value {
param($ProcessID);
# Close possible PowerShell instances
if ($Icinga2.PidManager.PidProcess($ProcessID) -ne $null) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
[string]::Format(
'Trying to terminate process with PID "{0}"',
$ProcessID
)
);
Stop-Process -Id $ProcessID -Force;
}
}
return $PidManager;

View file

@ -1,223 +0,0 @@
$ServerProtocoll = New-Object -TypeName PSObject;
$ServerProtocoll | Add-Member -membertype NoteProperty -name 'static' -value $FALSE;
$ServerProtocoll | Add-Member -membertype NoteProperty -name 'Client' -value $Null;
$ServerProtocoll | Add-Member -membertype NoteProperty -name 'Network' -value (Get-Icinga-Lib -Include 'NetworkProtocol');
$ServerProtocoll | Add-Member -membertype NoteProperty -name 'Response' -value (Get-Icinga-Lib -Include 'APIResponse');
$ServerProtocoll | Add-Member -membertype NoteProperty -name 'Timer' -value $Null;
$ServerProtocoll | Add-Member -membertype NoteProperty -name 'Message' -value $Null;
$ServerProtocoll | Add-Member -membertype NoteProperty -name 'Commands' -value @{};
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'Create' -value {
param([System.Net.Sockets.TcpClient]$Client);
$this.Client = $Client;
$this.Client.SendTimeout = 2000
$this.Client.NoDelay = $TRUE;
$this.Timer = [System.Diagnostics.Stopwatch]::StartNew();
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
'New incoming TCP Client connection'
);
$this.Network.Create($Client.GetStream());
# Just in case we received connections over HTTP, send a short answer message
# back and close the client request
if ($this.Network.encrypted -eq $FALSE) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Warning,
'Received client connection over HTTP. Rejecting client request.'
);
$this.Response.HTTPSRequired();
$this.Network.WriteMessage(
$this.Response.Compile()
);
$this.Close();
return $FALSE;
}
return $TRUE;
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'ParseRequest' -value {
# Tell our network protocol to read all messages until
# EOF is reached
[SecureString]$message = $this.Network.ReadMessage(-1);
if ($message -eq $null) {
return;
}
[hashtable]$ApiMessage = $Icinga2.Utils.WebHelper.ParseApiMessage($message);
if ($ApiMessage -eq $null -Or $ApiMessage.Count -eq 0) {
$this.SendInternalServerError();
return;
}
if ($Icinga2.Config.'authentication.enabled') {
[int]$Authenticated = $Icinga2.Utils.AuthHelper.Login(
$ApiMessage.credentials.user,
$ApiMessage.credentials.password,
$ApiMessage.credentials.domain
);
if ($Authenticated -eq 0) {
$this.SendAuthenticationRequired();
return;
}
}
if ($ApiMessage.headers.ContainsKey('content-length')) {
[int]$ContentLength = ($ApiMessage.headers['content-length'] - $ApiMessage.content.Length);
$ApiMessage.content += $Icinga2.Utils.SecureString.ConvertFrom(
$this.Network.ReadMessage(
$ContentLength
)
);
}
$this.Message = $ApiMessage;
$this.ParseQuery();
$this.ExecuteQuery();
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'ParseQuery' -value {
[string]$QueryString = $this.Message.base.query;
if ($QueryString[0] -eq '?') {
$QueryString = $QueryString.Substring(
1,
$QueryString.Length - 1
);
}
[array]$SplitCommand = $QueryString.Split('&');
foreach ($command in $SplitCommand) {
[hashtable]$data = $Icinga2.Utils.WebHelper.ParseUrlCommand($command);
if ($this.Commands.ContainsKey(($data.GetEnumerator() | Select-Object -First 1).Key) -eq $FALSE) {
$this.Commands += $data;
}
}
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'ExecuteQuery' -value {
switch($this.IsUrlPathValid(0)) {
'' {
switch($this.IsUrlPathValid(1)) {
'v1' {
switch($this.IsUrlPathValid(2)) {
'data' {
$this.ParseDataV1();
};
'modules' {
$this.ParseModulesV1();
};
default {
$this.SendBadRequest(
'Unsupported Cmdlets specified. The following Cmdlets are supported: data, modules'
);
};
}
};
default {
$this.SendBadRequest(
'Unsupported API version specified. The following versions are supported: v1'
);
};
}
};
default {
$this.SendInternalServerError();
};
}
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'GetExecutionTime' -value {
return $this.Timer.Elapsed.TotalSeconds;
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'ParseDataV1' -value {
[hashtable]$data =
@{
data = New-Icinga-Monitoring -Include $this.Commands.include -Exclude $this.Commands.exclude;
execution = $this.GetExecutionTime();
};
$this.Response.setContent($data);
$this.SendOkResponse();
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'ParseModulesV1' -value {
[hashtable]$modules =
@{
modules = New-Icinga-Monitoring -ListModules $TRUE;
execution = $this.GetExecutionTime();
};
$this.Response.setContent($modules);
$this.SendOkResponse();
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'IsUrlPathValid' -value {
param([int]$Index);
[string]$path = $this.Message.base.segments[$Index];
if ([string]::IsNullOrEmpty($path) -eq $TRUE) {
return 'default';
}
return $path.Replace('/', '');
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'SendOkResponse' -value {
$this.Network.WriteMessage(
$this.Response.Compile()
);
$this.Close();
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'SendInternalServerError' -value {
$this.Response.InternalServerError();
$this.Network.WriteMessage(
$this.Response.Compile()
);
$this.Close();
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'SendAuthenticationRequired' -value {
$this.Response.AuthenticationRequired();
$this.Network.WriteMessage(
$this.Response.Compile()
);
$this.Close();
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'SendBadRequest' -value {
param([string]$message);
$this.Response.CustomBadRequest($message);
$this.Network.WriteMessage(
$this.Response.Compile()
);
$this.Close();
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'Close' -value {
try {
$this.Timer.Stop();
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
'Closing TCP Client connection'
)
$this.Client.Close();
$this.Client.Dispose()
$this.Client = $Null;
} catch {
# Nothing to handle. If the connection is closed already, ignore it.
}
}
return $ServerProtocoll;

View file

@ -1,183 +0,0 @@
$Service = New-Object -TypeName PSObject;
$Service | Add-Member -membertype NoteProperty -name 'servicename' -value 'IcingaWindowsModule';
$Service | Add-Member -membertype NoteProperty -name 'servicedisplayname' -value 'Icinga Windows Service';
$Service | Add-Member -membertype ScriptMethod -name 'Install' -value {
param([string]$ServiceBinaryPath);
if ([string]::IsNullOrEmpty($ServiceBinaryPath) -eq $TRUE) {
return 'Please specify a valid service binary path.';
}
# Test if our binary does exist
if (-Not (Test-Path $ServiceBinaryPath)) {
return ([string]::Format(
'Failed to install the Icinga service. The service binary specified at "{0}" does not exist.',
$ServiceBinaryPath
));
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
'Trying to install Icinga 2 Service...'
);
# Now add the script root which we require to include to the service
$ServiceBinaryPath = [string]::Format(
'{0} \"{1}\"',
$ServiceBinaryPath,
(Join-Path -Path $Icinga2.App.RootPath -ChildPath $Icinga2.App.ModuleName)
);
$result = & sc.exe create $this.servicename binPath= "$ServiceBinaryPath" DisplayName= $this.servicedisplayname start= auto;
if ($this.HandleServiceError($LASTEXITCODE) -eq $TRUE) {
return $FALSE;
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
'Successfully installed the Icinga 2 Windows Service.'
);
return $TRUE;
}
$Service | Add-Member -membertype ScriptMethod -name 'Uninstall' -value {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
'Trying to uninstall Icinga Service...'
);
# Stop the service before uninstalling it
$this.Stop();
$result = & sc.exe delete $this.servicename;
if ($this.HandleServiceError($LASTEXITCODE) -eq $TRUE) {
return $FALSE;
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
'Successfully uninstalled the Icinga 2 Windows Service.'
);
return $TRUE;
}
$Service | Add-Member -membertype ScriptMethod -name 'Start' -value {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
'Trying to start Icinga 2 Service...'
);
$result = & sc.exe start $this.servicename;
if ($this.HandleServiceError($LASTEXITCODE) -eq $TRUE) {
return;
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
'Successfully started the Icinga 2 Service.'
);
$this.QueryStatus();
}
$Service | Add-Member -membertype ScriptMethod -name 'Stop' -value {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
'Trying to stop Icinga 2 Service...'
);
$result = & sc.exe stop ($this.servicename);
if ($this.HandleServiceError($LASTEXITCODE) -eq $TRUE) {
return;
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
'Successfully stopped the Icinga 2 Service.'
);
$this.QueryStatus();
}
$Service | Add-Member -membertype ScriptMethod -name 'Restart' -value {
$this.Stop();
# Wait two seconds before starting the service again
Start-Sleep -Seconds 2;
$this.Start();
}
$Service | Add-Member -membertype ScriptMethod -name 'QueryStatus' -value {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
'Waiting to query the proper Icinga 2 Service status...'
);
Start-Sleep -Seconds 1;
$this.Status();
}
$Service | Add-Member -membertype ScriptMethod -name 'Status' -value {
$ServiceStatus = (Get-WMIObject win32_service -Filter (
[string]::Format(
"Name='{0}'",
($this.servicename)
)
)).State;
if ([string]::IsNullOrEmpty($ServiceStatus) -eq $TRUE) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Warning,
$Icinga2.Enums.ServiceStatus.NotInstalled
);
return;
}
if ($Icinga2.Enums.ServiceStatus.ContainsKey($ServiceStatus)) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
$Icinga2.Enums.ServiceStatus.$ServiceStatus
);
} else {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
[string]::Format(
'The Icinga service status is {0}',
$ServiceStatus
)
);
}
}
$Service | Add-Member -membertype ScriptMethod -name 'HandleServiceError' -value {
param([int]$ErrorCode);
# Nothing to do as no error occured
if ($ErrorCode -eq 0) {
return $FALSE;
}
if ($Icinga2.Enums.SCErrorCodes.ContainsKey($ErrorCode)) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Error,
$Icinga2.Enums.SCErrorCodes.$ErrorCode
);
} else {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Error,
([string]::Format('Failed to execute operation for Icinga 2 Service: {0}', $result))
);
}
return $TRUE;
}
return $Service;

View file

@ -1,23 +0,0 @@
$SystemCPU = Get-CimInstance -ClassName 'Win32_Processor';
[int]$NumberOfCPUCores = 0;
[int]$NumberOfCPUThreads = 0;
if (($SystemCPU.NumberOfCores).GetType() -is [Object]) {
$SystemCPU.NumberOfCores | Foreach { $NumberOfCPUCores += $_; };
} else {
$NumberOfCPUCores = $SystemCPU.NumberOfCores;
}
if (($SystemCPU.NumberOfLogicalProcessors).GetType() -is [Object]) {
$SystemCPU.NumberOfLogicalProcessors | Foreach { $NumberOfCPUThreads += $_; };
} else {
$NumberOfCPUThreads = $SystemCPU.NumberOfCores;
}
[hashtable]$Overview = @{
'NumberOfCPUCores' = $NumberOfCPUCores;
'NumberOfCPUThreads' = $NumberOfCPUThreads;
};
return $Overview;

View file

@ -1,76 +0,0 @@
$TCPDaemon = New-Object -TypeName PSObject;
$TCPDaemon | Add-Member -membertype ScriptMethod -name 'Start' -value {
[int]$Port = $Icinga2.Config.'tcp.socket.port';
if (-Not $Icinga2.Cache.Certificates.Server) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Error,
[string]::Format(
'Unable to start TCP socket daemon for port {0}. No valid SSL certificate was loaded.',
$Port
)
);
return;
}
if ($Icinga2.TCPSocket.IsSocketOpenAndValid($Port) -eq $TRUE) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
[string]::Format(
'A PowerShell instance for socket on port "{0}" is already running with PID "{1}"',
$Port,
$Icinga2.PidManager.GetPIDByBind($port)
)
);
return;
}
$TCPSocket = $Icinga2.TCPSocket.CreateTCPSocket($Port);
if ($TCPSocket -eq $null) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Error,
[string]::Format(
'Failed to start TCP socket on port "{0}"',
$Port
)
)
return;
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
[string]::Format(
'Starting new API listener on port "{0}"',
$Port
)
);
while($true) {
[System.Net.Sockets.TcpClient]$client = $TCPSocket.AcceptTcpClient();
$ServerProtocol = Get-Icinga-Lib -Include 'ServerProtocol';
if ($ServerProtocol.Create($Client) -eq $FALSE) {
continue;
}
$ServerProtocol.ParseRequest();
}
$Icinga2.TCPSocket.CloseTCPSocket($Port);
}
$TCPDaemon | Add-Member -membertype ScriptMethod -name 'Stop' -value {
if ($Icinga2.Utils.AdminShell.IsAdminShell() -eq $FALSE) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Error,
'Please run this shell as Administrator in order to stop daemon processes'
);
return;
}
[int]$Port = $Icinga2.Config.'tcp.socket.port';
$Icinga2.TCPSocket.CloseTCPSocket($Port);
}
return $TCPDaemon;

View file

@ -1,161 +0,0 @@
$TCPSocket = New-Object -TypeName PSObject;
$TCPSocket | Add-Member -membertype ScriptMethod -name 'CreateTCPSocket' -value {
param([int]$port);
[string]$PidFile = $Icinga2.PidManager.PidFileName($port);
try {
$TCPSocket = [System.Net.Sockets.TcpListener]$port;
$TCPSocket.Start();
$Icinga2.Cache.Sockets.Add($PidFile, $TCPSocket);
$Icinga2.PidManager.CreatePidFile($port);
return $TCPSocket;
} catch {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
[string]::Format(
'Failed to create TCP socket on port "{0}": {1}',
$port,
$_.Exception.Message
)
);
}
return $null;
}
# Properly close sockets, flush PID Files or terminate PowerShell instances as owner of sockets
$TCPSocket | Add-Member -membertype ScriptMethod -name 'CloseTCPSocket' -value {
param([int]$port);
[string]$PidFile = $Icinga2.PidManager.PidFileName($port);
[bool]$IsExternalSocket = $FALSE;
# Clear our Socket cache
# In case the socket does not exist, create a new socket
if ($Icinga2.Cache.Sockets.ContainsKey($PidFile) -eq $FALSE) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
[string]::Format(
'The socket of port "{0}" is not part of this PowerShell instance',
$port
)
);
$IsExternalSocket = $TRUE;
} else {
try {
$TCPSocket = $Icinga2.Cache.Sockets.$PidFile;
$TCPSocket.Stop();
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
[string]::Format(
'Closing TCP socket on port "{0}"',
$port
)
);
} catch {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
[string]::Format(
'Failed to close TCP socket on port "{0}": {1}',
$port,
$_.Exception.Message
)
);
}
$Icinga2.Cache.Sockets.Remove($PidFile);
}
# Delete the PID file from disk in case it exists
[string]$FullPidPath = $Icinga2.PidManager.FullPidPath($PidFile);
[int]$ProcessID = $Icinga2.PidManager.ProcessID($FullPidPath);
$Icinga2.PidManager.RemovePidFile($FullPidPath);
# Close possible PowerShell instances
if ($Icinga2.PidManager.PidProcess($ProcessID) -ne $null) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
[string]::Format(
'Trying to terminate process with PID "{0}"',
$ProcessID
)
);
Stop-Process -Id $ProcessID -Force;
}
}
$TCPSocket | Add-Member -membertype ScriptMethod -name 'IsSocketOpenAndValid' -value {
param([int]$port);
[string]$PidFile = $Icinga2.PidManager.PidFileName($port);
[string]$FullPidPath = $Icinga2.PidManager.FullPidPath($PidFile);
if ((Test-Path $FullPidPath) -eq $FALSE) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Warning,
[string]::Format(
'No PID-File found for TCP socket on port "{0}". Trying to close socket...',
$port
)
);
# Even when the PID-File does not exist, try to gracefull shutdown the socket
$this.CloseTCPSocket($port);
return $FALSE;
}
[int]$ProcessID = $Icinga2.PidManager.ProcessID($FullPidPath);
if ([string]::IsNullOrEmpty($ProcessID) -eq $TRUE) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Warning,
[string]::Format(
'No process ID found for socket on port "{0}". Trying to close socket anyway...',
$port
)
);
# Even when the PID-File does not exist, try to gracefull shutdown the socket
$this.CloseTCPSocket($port);
return $FALSE;
}
try {
# Look for the Process over WMI, as we might run as Service User and require
# to fetch the entire scope of running processes
if ($Icinga2.PidManager.PidProcess($ProcessID) -ne $null) {
return $TRUE;
}
# Socket does not exist or is not valid. Perform a cleanup and return false
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Warning,
[string]::Format(
'The socket configuration for port "{0}" is not valid. Performing cleanup...',
$port
)
);
$this.CloseTCPSocket($port);
return $FALSE;
} catch [System.Exception] {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
[string]::Format(
'Exception while trying to lookup the process for socket port "{0}": {1}...',
$port,
$_.Exception.Message
)
);
}
$this.CloseTCPSocket($port);
return $FALSE;
}
return $TCPSocket;

View file

@ -1,12 +0,0 @@
# Provide a collection of utility functions for the module
[hashtable]$Utils = @{};
Get-ChildItem (Join-Path -Path $PSScriptRoot -ChildPath '\utils\') -Filter *.ps1 |
Foreach-Object {
$path = $_.FullName;
$name = $_.Name.Replace('.ps1', '');
$Utils.Add($name, (& $path));
}
return $Utils;

View file

@ -1,12 +0,0 @@
$AdminShell = New-Object -TypeName PSObject;
$AdminShell | Add-Member -membertype ScriptMethod -name 'IsAdminShell' -value {
$CurrentIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent();
$WindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($CurrentIdentity);
if (-Not $WindowsPrincipal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) {
return $FALSE;
}
return $TRUE;
}
return $AdminShell;

View file

@ -1,63 +0,0 @@
Add-Type -AssemblyName System.DirectoryServices.AccountManagement;
$AuthHelper = New-Object -TypeName PSObject;
<#
# This function will allow us to authenticate against either a
# Domain Controller or the local machine the module runs on.
# For security reasons, Username and Password have to be
# stored within a SecureString. If no Domain is specified,
# a login will always be attempted to the local machine
#>
$AuthHelper | Add-Member -membertype ScriptMethod -name 'Login' -value {
param([SecureString]$UserName, [SecureString]$Password, [String]$Domain);
# Base handling: We try to authenticate against a local user on the machine
[string]$AuthMethod = [System.DirectoryServices.AccountManagement.ContextType]::Machine;
[string]$AuthDomain = $env:COMPUTERNAME;
# If we specify a domain, we should authenticate against our Domain
if ([string]::IsNullOrEmpty($Domain) -eq $FALSE) {
$AuthMethod = [System.DirectoryServices.AccountManagement.ContextType]::Domain;
$AuthDomain = $Domain;
}
try {
# Create an Account Management object based on the above determined settings
$AccountService = New-Object System.DirectoryServices.AccountManagement.PrincipalContext(
$AuthMethod,
$AuthDomain
);
} catch {
# Regardless of the error, print the message and return false to prevent further execution
$Icinga2.Log.Write($Icinga2.Enums.LogState.Exception, $_.Exception.Message);
return 0;
}
# In case we couldn't setup the Account Service, always return false
if ($AccountService -eq $null) {
return 0;
}
try {
# Try to authenticate and either return true or false as integer
[int]$AuthResult = [int]($AccountService.ValidateCredentials(
$Icinga2.Utils.SecureString.ConvertFrom($UserName),
$Icinga2.Utils.SecureString.ConvertFrom($Password)
));
return $AuthResult;
} catch {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format(
'Failed to authenticate with the provided user credentials. Error: {0}',
$_.Exception.Message
)
);
}
return 0;
}
return $AuthHelper;

View file

@ -1,75 +0,0 @@
<#
# Helper class allowing to read INI files basicly
# and return the content as Hashtable
#>
$IniParser = New-Object -TypeName PSObject;
$IniParser | Add-Member -membertype ScriptMethod -name 'LoadFromArray' -value {
param([array]$content, [bool]$CutLastSpace);
[hashtable]$IniContent = @{};
[string]$IniKey = '';
[string]$SubIniKey = '';
# First, loop all lines of our NTP config
foreach ($item in $content) {
# At first we require to parse the section argument for the config
if ($item.Contains('[')) {
$IniKey = $item.Replace('[', '').Replace(']', '');
$IniContent.Add($IniKey, @{ });
continue;
}
if ([string]::IsNullOrEmpty($item) -eq $TRUE) {
continue;
}
# In case our entry does not contain ':', we are not loading a config entry
if ($item.Contains(':') -eq $FALSE) {
$SubIniKey = $item;
$IniContent[$IniKey].Add($SubIniKey, @{ });
continue;
}
# Now as we found an config entry point, split the result at first to get
# the key of our config. Afterwards we load the value by removing all
# spaces before the actual value
[array]$ConfigData = $item.Split(':');
[string]$ConfigKey = $ConfigData[0];
[string]$ConfigValue = $item.Substring($item.IndexOf(':') + 1, $item.Length - $item.IndexOf(':') - 1);
# Some INI files (like NTP) add additional details behind the values if they
# are configured by Local or Remote for example. With this we can cut these
# informations out, idependently from our configured OS language
if ($CutLastSpace -eq $TRUE) {
$ConfigValue = $ConfigValue.Substring(0, $ConfigValue.LastIndexOf(' '));
}
while ($ConfigValue[0] -eq ' ') {
$ConfigValue = $ConfigValue.Substring(1, $ConfigValue.Length - 1);
}
# It could happen that within a section keys are being overwritten again
# We should take care of this and update a possible added key with the
# next configured values to receive only the correct configuration as result
# as it is interpreted by the time service
if ([string]::IsNullOrEmpty($SubIniKey) -eq $TRUE) {
if ($IniContent[$IniKey].ContainsKey($ConfigKey) -eq $FALSE) {
$IniContent[$IniKey].Add($ConfigKey, $ConfigValue);
} else {
$IniContent[$IniKey][$ConfigKey] = $ConfigValue;
}
} else {
if ($IniContent[$IniKey][$SubIniKey].ContainsKey($ConfigKey) -eq $FALSE) {
$IniContent[$IniKey][$SubIniKey].Add($ConfigKey, $ConfigValue);
} else {
$IniContent[$IniKey][$SubIniKey][$ConfigKey] = $ConfigValue;
}
}
}
return $IniContent;
}
return $IniParser;

View file

@ -1,154 +0,0 @@
<#
# Helper class for accessing and handling modules in a
# more easier and managed way
#>
$Modules = New-Object -TypeName PSObject;
$Modules | Add-Member -membertype ScriptMethod -name 'LoadIncludes' -value {
param([string]$modulename, $Config);
$modulename = $modulename.ToLower();
$modulename = $modulename.Replace('.ps1', '');
[string]$ModuleDir = Join-Path `
-Path $Icinga2.App.RootPath `
-ChildPath (
[string]::Format(
'\modules\include\{0}',
$modulename
)
)
[hashtable]$ModuleIndludes = @{};
if ( (Test-Path $ModuleDir) -eq $FALSE) {
return $ModuleIndludes;
}
Get-ChildItem $ModuleDir -Filter *.ps1 |
Foreach-Object {
[string]$name = $_.Name.ToLower().Replace(
'.ps1',
''
);
try {
$ModuleIndludes.Add(
$name,
(& $_.FullName -Config $Config)
);
} catch {
$ModuleIndludes.Add(
$name,
[string]::Format(
'Failed to execute include "{0}" for module "{1}". Exception: {2}',
$name,
$modulename,
$_.Exception.Message
)
);
}
}
return $ModuleIndludes;
}
$Modules | Add-Member -membertype ScriptMethod -name 'FlushModuleCache' -value {
param([string]$modulename);
if ($Icinga2.Cache.Modules.ContainsKey($modulename) -eq $FALSE) {
return;
}
$Icinga2.Cache.Modules[$modulename] = @{ };
}
$Modules | Add-Member -membertype ScriptMethod -name 'AddCacheElement' -value {
param([string]$modulename, [string]$cachename, $value);
if ($Icinga2.Cache.Modules.ContainsKey($modulename) -eq $FALSE) {
$Icinga2.Cache.Modules.Add($modulename, @{ });
}
if ($Icinga2.Cache.Modules[$modulename].ContainsKey($cachename) -eq $FALSE) {
$Icinga2.Cache.Modules[$modulename].Add($cachename, $value);
} else {
$Icinga2.Cache.Modules[$modulename][$cachename] = $value;
}
}
$Modules | Add-Member -membertype ScriptMethod -name 'GetCacheElement' -value {
param([string]$modulename, [string]$cachename);
if ($Icinga2.Cache.Modules.ContainsKey($modulename) -eq $FALSE) {
return @{ };
}
if ($Icinga2.Cache.Modules[$modulename].ContainsKey($cachename) -eq $FALSE) {
return @{ };
}
return $Icinga2.Cache.Modules[$modulename][$cachename];
}
$Modules | Add-Member -membertype ScriptMethod -name 'GetHashtableDiff' -value {
param([hashtable]$new, [hashtable]$cache, [array]$addkeys);
[hashtable]$DiffTable = @{
FullList = @{ };
Removed = @( );
Added = $null;
Modified = @{ };
}
if ($cache -eq $null -or $cache.Count -eq 0) {
$DiffTable.FullList = $new;
} else {
# Each additional call will only send the diffs to the server
$int = 0;
foreach ($cachedProcess in $cache.Keys) {
$oldProcess = $cache[$cachedProcess];
# In case a service is no longer present on our system, send the process Id
# only so we can delete it from our database
if ($new.ContainsKey($cachedProcess) -eq $FALSE) {
$DiffTable['Removed'] += $oldProcess.ProcessId;
} else {
# If we know about a process, only send the values which have been updated
# since the last check
$newProcess = $new[$cachedProcess];
foreach ($entry in $newProcess.Keys) {
$oldValue = $oldProcess[$entry];
$newValue = $newProcess[$entry];
if ($oldValue -ne $newValue) {
if ($DiffTable['Modified'].ContainsKey($cachedProcess) -eq $FALSE) {
$DiffTable['Modified'].Add($cachedProcess, @{ });
}
$DiffTable['Modified'][$cachedProcess].Add($entry, $newValue);
}
}
if ($DiffTable['Modified'].ContainsKey($cachedProcess) -eq $TRUE) {
foreach($entry in $addkeys) {
if ($DiffTable['Modified'][$cachedProcess].ContainsKey($entry) -eq $FALSE -and
$newProcess.ContainsKey($entry) -eq $TRUE) {
$DiffTable['Modified'][$cachedProcess].Add($entry, $newProcess[$entry]);
}
}
}
$new.Remove($cachedProcess);
}
}
# All other processes are new and should be added
$DiffTable['Added'] = $new;
}
return $DiffTable;
}
return $Modules;

View file

@ -1,111 +0,0 @@
$SSL = New-Object -TypeName PSObject;
$SSL | Add-Member -membertype ScriptMethod -name 'LoadServerCertificate' -value {
if ((Get-Icinga-Setup) -eq $FALSE) {
$Icinga2.Log.WriteConsole(
$Icinga2.Enums.LogState.Warning,
'The module has not been configured yet. Skipping certificate loading'
);
return;
}
try {
$CertStore = New-Object System.Security.Cryptography.X509Certificates.X509Store(
$Icinga2.Config.'certstore.name',
$Icinga2.Config.'certstore.location'
);
$CertStore.Open("ReadOnly");
$ServerCertificate = $null;
[string]$CertName = $Icinga2.Config.'certstore.certificate.name';
[string]$CertThumbprint = $Icinga2.Config.'certstore.certificate.thumbprint';
# Try to discover the certificate based on our FQDN
if ([string]::IsNullOrEmpty($CertName) -eq $TRUE -And [string]::IsNullOrEmpty($CertThumbprint) -eq $TRUE) {
$CertName = [System.Net.Dns]::GetHostEntry('localhost').HostName;
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format(
'Trying to discover certificate for this host with FQDN "{0}"',
$CertName
)
);
}
foreach ($cert in $CertStore.Certificates) {
if ([string]::IsNullOrEmpty($CertThumbprint) -eq $FALSE) {
if ($CertThumbprint.ToLower() -eq $cert.Thumbprint.ToLower()) {
$ServerCertificate = $cert;
break;
}
}
if ([string]::IsNullOrEmpty($CertName) -eq $FALSE) {
[string]$CNCertName = [string]::Format('CN={0}', $CertName.ToLower());
if ($CNCertName.ToLower() -eq $cert.Subject.ToLower()) {
$ServerCertificate = $cert;
try {
$result = Test-Certificate -Cert $cert -ErrorAction SilentlyContinue -WarningAction SilentlyContinue;
if ($result -eq $FALSE) {
continue;
}
} catch {
continue;
}
break;
}
}
}
$certificate = $null;
if ($ServerCertificate -ne $null) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format(
'Using certificate "{0}" with thumbprint "{1}"',
$ServerCertificate.Subject,
$ServerCertificate.Thumbprint
)
);
$certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2;
$certificate.Import($ServerCertificate.RawData)
}
$CertStore.Close();
return $certificate;
} catch [System.ComponentModel.Win32Exception] {
# This error occures in case we provide a cert store and location which is not accessable
# from our current user. We have to simply drop everything and close every possible
# connection
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
'SSL-Error: Unable to access provided certificate from the user space this module is started with.'
);
} catch [System.NotSupportedException] {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
'The used SSL certificate is not providing a linked private key and cannot be used as Server certificate'
);
} catch {
# Handle every other error here
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
$_.Exception.Message
);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
$_.Exception
);
}
return $null;
}
return $SSL;

View file

@ -1,29 +0,0 @@
<#
# Helper class allowing to easily convert strings into SecureStrings
# and vice-versa
#>
$SecureString = New-Object -TypeName PSObject;
$SecureString | Add-Member -membertype ScriptMethod -name 'ConvertTo' -value {
param([string]$string);
[SecureString]$SecureString = ConvertTo-SecureString -AsPlainText $string -Force;
return $SecureString;
}
$SecureString | Add-Member -membertype ScriptMethod -name 'ConvertFrom' -value {
param([SecureString]$SecureString);
if ($SecureString -eq $null) {
return '';
}
[IntPtr]$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
[string]$String = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
return $String;
}
return $SecureString;

View file

@ -1,296 +0,0 @@
$WebHelper = New-Object -TypeName PSObject;
$WebHelper | Add-Member -membertype ScriptMethod -name 'ParseApiMessage' -value {
param([SecureString]$message);
try {
[hashtable]$HeaderContent = @{};
if ($message -eq $null) {
return $HeaderContent;
}
[string]$HTMLMessage = $Icinga2.Utils.SecureString.ConvertFrom($message);
[string]$HTMLContent = '';
if ($HTMLMessage.Contains("`r`n`r`n")) {
[int]$EOFIndex = $HTMLMessage.IndexOf("`r`n`r`n") + 4;
$HTMLContent = $HTMLMessage.Substring(
$EOFIndex,
$HTMLMessage.Length - $EOFIndex
);
# Remove the content from our message
if ([string]::IsNullOrEmpty($HTMLContent) -eq $FALSE) {
$HTMLMessage = $HTMLMessage.Replace($HTMLContent, '');
}
}
[array]$SingleHeaders = $HTMLMessage.Split("`r`n");
$HTMLMessage = $null;
# At first read the method, the http call and the protocol
$HeaderContent.Add(
'base',
$this.ParseMethodAndUrl($SingleHeaders[0])
);
# Now add possible content to our hashtable
$HeaderContent.Add(
'content',
$HTMLContent
);
# Drop the first entry of the array, as we no longer require it
$SingleHeaders = $SingleHeaders | Select-Object -Skip 1;
# Read the headers from the array
$HeaderContent.Add(
'headers',
$this.ParseHeaders($SingleHeaders)
);
# Flush the array from the memory
$SingleHeaders = $null;
if ($HeaderContent.headers.ContainsKey('Authorization')) {
$HeaderContent.Add(
'credentials',
$this.ParseUserCredentials(
$HeaderContent.headers.Authorization
)
);
$HeaderContent.headers.Remove('Authorization');
}
return $HeaderContent;
}
catch {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
[string]::Format(
'Failed to parse HTTP content and headers. Error {0}',
$_.Exception.Message
)
);
}
return $null;
}
$WebHelper | Add-Member -membertype ScriptMethod -name 'ParseMethodAndUrl' -value {
param([string]$message);
[array]$Content = $message.Split(' ');
[uri]$UriData = [uri][string]::Format(
'https://localhost{0}',
$Content[1]
);
return @{
method = $Content[0];
call = [System.Web.HttpUtility]::UrlDecode(
$Content[1]
);
protocol = $Content[2];
segments = $UriData.Segments;
query = [System.Web.HttpUtility]::UrlDecode(
$UriData.Query
);
}
}
$WebHelper | Add-Member -membertype ScriptMethod -name 'ParseHeaders' -value {
param([array]$message);
[hashtable]$Headers = @{};
foreach ($header in $message) {
[string]$HeaderName = '';
[string]$HeaderValue = '';
# Skip empty array values
if ([string]::IsNullOrEmpty($header) -eq $FALSE) {
if ($header.Contains(':')) {
[array]$Element = $header.Split(':');
$HeaderName = $Element[0];
if ($Element.Count -gt 1) {
for ($i = 1; $i -le ($Element.Count - 1); $i++) {
$HeaderValue = -Join(
$HeaderValue,
$Element[$i],
':'
);
}
}
# Remove the last added ':' at the end of the string
if ($HeaderValue.Length -gt 1) {
$HeaderValue = $HeaderValue.Substring(
0,
$HeaderValue.Length - 1
);
}
# In case the first letter of our value is a space, remove it
while ($HeaderValue[0] -eq ' ') {
$HeaderValue = $HeaderValue.Substring(
1,
$HeaderValue.Length - 1
);
}
if ($Headers.ContainsKey($HeaderName) -eq $FALSE) {
# We have to modify the Authorization header value a little more and also
# ensure we store it as secure string within our module
if ($HeaderName -eq 'Authorization') {
[array]$AuthArray = $HeaderValue.Split(' ');
# TODO: Shall we handle each auth type differently?
$Headers.Add(
$HeaderName,
$Icinga2.Utils.SecureString.ConvertTo($AuthArray[1])
);
$AuthArray = $null;
} else {
$Headers.Add($HeaderName, $HeaderValue);
}
}
} else {
$Headers.Add($header, $null);
}
}
}
return $Headers;
}
$WebHelper | Add-Member -membertype ScriptMethod -name 'ParseUserCredentials' -value {
param([SecureString]$Base64String);
[hashtable]$Credentials = @{};
if ($Base64String -eq $null) {
return $Credentials;
}
# Convert the Base64 Secure String back to a normal string
[string]$PlainAuth = [System.Text.Encoding]::UTF8.GetString(
[System.Convert]::FromBase64String(
$Icinga2.Utils.SecureString.ConvertFrom($Base64String)
)
);
$Base64String = $null;
# If no ':' is within the string, the credential data is not properly formated
if ($PlainAuth.Contains(':') -eq $FALSE) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Warning,
'Received invalid formated credentials as Base64 encoded.'
);
$PlainAuth = $null;
return $Credentials;
}
try {
# Build our User Data and Password from the string
[string]$UserData = $PlainAuth.Substring(
0,
$PlainAuth.IndexOf(':')
);
$Credentials.Add(
'password',
$Icinga2.Utils.SecureString.ConvertTo(
$PlainAuth.Substring(
$PlainAuth.IndexOf(':') + 1,
$PlainAuth.Length - $UserData.Length - 1
)
)
);
$PlainAuth = $null;
# Extract a possible domain
if ($UserData.Contains('\')) {
# Split the auth string on the '\'
[array]$AuthData = $UserData.Split('\');
# First value of the array is the Domain, second is the Username
$Credentials.Add('domain', $AuthData[0]);
$Credentials.Add(
'user',
$Icinga2.Utils.SecureString.ConvertTo(
$AuthData[1]
)
);
$AuthData = $null;
} else {
$Credentials.Add('domain', $null);
$Credentials.Add(
'user',
$Icinga2.Utils.SecureString.ConvertTo(
$UserData
)
);
}
$UserData = $null;
} catch {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Error,
'Failed to handle authentication request. An exception occured while processing the request.'
);
}
return $Credentials;
}
$WebHelper | Add-Member -membertype ScriptMethod -name 'ParseUrlCommand' -value {
param([string]$Argument);
[hashtable]$StructuredCommand = @{};
# If no = is included, we don't need to handle anything special
if ($Argument.Contains('=') -eq $FALSE) {
$StructuredCommand.Add($Argument, $null);
return $StructuredCommand;
}
[int]$SeperatorIndex = $Argument.IndexOf('=');
[string]$Command = $Argument.Substring(
0,
$SeperatorIndex
);
$Command = $Command.Replace(' ', '').ToLower();
[array]$Values = @();
[string]$Value = $Argument.Substring(
$SeperatorIndex + 1,
$Argument.Length - $SeperatorIndex - 1
);
if ($Value.Contains(',') -eq $TRUE) {
[array]$Entries = $Value.Split(',');
foreach ($entry in $Entries) {
[string]$ParsedValue = $entry;
# Cut spaces before names of inputs
while ($ParsedValue[0] -eq ' ') {
$ParsedValue = $ParsedValue.Substring(
1,
$ParsedValue.Length - 1
);
}
# Cut spaces after names of inputs
while ($ParsedValue[$ParsedValue.Length - 1] -eq ' ') {
$ParsedValue = $ParsedValue.Substring(
0,
$ParsedValue.Length - 1
);
}
$Values += $ParsedValue.ToLower();
}
} else {
$Values += $Value.Replace(' ', '').ToLower();
}
# Filter out duplicate entries
$Values = $Values | Select-Object -Unique;
$StructuredCommand.Add($Command, $Values);
return $StructuredCommand;
}
return $WebHelper;

View file

@ -1,100 +0,0 @@
# This script will initialse the entire module configuration for easier usage
param (
[string]$RootDirectory = '',
[string]$ModuleName = ''
);
# Create an internal 'namespace' for our environment
Set-Variable -Name Icinga2 -Option Constant -Value @{
Function = @(
'Use-Icinga',
'Import-IcingaLib',
'Get-IcingaPluginDir',
'Get-IcingaCustomPluginDir',
'Get-IcingaCacheDir',
'Get-IcingaPowerShellConfigDir',
'Get-Icinga-Lib',
'Get-Icinga-Object',
'Get-Icinga-Service',
'Start-Icinga-Service',
'Stop-Icinga-Service',
'Restart-Icinga-Service',
'Install-Icinga-Service',
'Uninstall-Icinga-Service',
'Install-Icinga',
'Get-Icinga-Setup',
'Start-Icinga-Daemon',
'Stop-Icinga-Daemon',
'Start-Icinga-Checker',
'Stop-Icinga-Checker',
'Get-Icinga-Command',
'New-Icinga-Monitoring',
'Get-Icinga-Counter',
'Get-Icinga-Config',
'Set-Icinga-Config',
'Remove-Icinga-Config',
'New-Icinga-Config'
);
}
# Define temporary variables to store the main current root and module name
# Note: Never use this variables within the module besides inside '\core\includes\'
$_InternalTempVariables = @{
RootPath = $RootDirectory;
ModuleName = $ModuleName;
}
# End definition of temporary variables
# Load all PowerShell scripts within our '\core\include\' directory and add the content with the name
# of the script into our namespace
Get-ChildItem (Join-Path -Path $PSScriptRoot -ChildPath '\include\') -Filter *.ps1 |
Foreach-Object {
$path = $_.FullName;
$name = $_.Name.Replace('.ps1', '');
# Add variables to a global namespace. Should only be used within the
# same PowerShell instance
try {
$include = (& $path);
} catch {
Write-Host (
[string]::Format(
'Failed to execute core module "{0}". Exception: {1}',
$name,
$_.Exception.Message
)
);
}
if ([bool]($include.PSobject.Properties.Name -eq 'static') -eq $FALSE -Or $include.static -eq $TRUE) {
$Icinga2.Add($name, $include);
}
}
# Flush the internal temp variable cache
$_InternalTempVariables = $null;
# Load our System.Web helper class
[Reflection.Assembly]::LoadWithPartialName("System.Web") | Out-Null;
$Icinga2.Add(
'Cache',
@{
# This will allow us to dynamicly initialise Performance Counters during
# startup to speed up actual checks later on. Of course counters will be
# cached anyway once they are executed, but will speed up first check
# executions for CPU Performance Counters for example
PerformanceCounter = @{ };
# Pre-Load the Server SSL Certificate
Certificates = @{ Server = $Icinga2.Utils.SSL.LoadServerCertificate() };
# Create a instance for storing TCP Sockets (in case we later want to listen in multi-sockets)
Sockets = @{ };
# Store our checker configuration we receive from the remote endpoint
Checker = @{ };
# This cache can be used for storing informations of modules to compare send informations
# as well as required data for a later execution of the same module again
Modules = @{ };
}
);
return $Icinga2;

View file

@ -1,118 +0,0 @@
param(
[array]$Include = @(),
[array]$Exclude = @(),
[boolean]$ListModules = $FALSE,
$Config = $null,
[string]$AgentRoot = ''
)
function ClassMonitoring()
{
param(
[array]$Include = @(),
[array]$Exclude = @(),
[boolean]$ListModules = $FALSE,
$Config = $null,
[string]$AgentRoot = ''
)
[string]$ModuleDirectory = Join-Path $AgentRoot -ChildPath 'modules';
[hashtable]$ModuleList = @{};
[array]$AvailableModules = @();
$ResultList = New-Object psobject -prop @{};
# Let's do a small fix here: We have defined 'include' within the URL, but
# we haven't specified any values. So lets assume we want to load all
# modules
if ($Include.Count -eq 1 -And [string]::IsNullOrEmpty($Include[0])) {
$Include[0] = '*';
}
# In case no includes are specified, lets include everything
if ($Include.Count -eq 0) {
$Include += '*';
}
<#
# In case no filter is specified, we asume we want to collect everything.
# Lets fetch all PowerShell Scripts within our module Directory
# Will also be used to return a list of installed modules
#>
if (($Include.Count -eq 1 -And $Include[0] -eq '*') -Or $ListModules) {
Get-ChildItem $ModuleDirectory -Filter *.ps1 |
Foreach-Object {
$path = $_.FullName
$name = $_.Name.Replace('.ps1', '').ToLower();
$ModuleList.Add($name, $path);
$AvailableModules += $name;
}
if ($ListModules) {
return $AvailableModules;
}
} else {
# In case we provided a filter, try to locate these modules
foreach ($module in $Include) {
# Just to ensure we skip this argument in case it is provided
if ($module -eq '*') {
continue;
}
$module = $module.ToLower();
[string]$file = [string]::Format('{0}.ps1', $module);
[string]$path = Join-Path $ModuleDirectory -ChildPath $file;
if ($ModuleList.ContainsKey($module) -eq $FALSE) {
$ModuleList.Add($module, $path);
}
}
}
foreach ($module in $Exclude) {
if ($ModuleList.ContainsKey($module)) {
$ModuleList.Remove($module);
}
}
[System.Diagnostics.Stopwatch]$ModuleTimer = New-Object System.Diagnostics.Stopwatch;
# Now as we have our module list available, lets execute them to fetch informations
foreach ($module in $ModuleList.Keys) {
$ModuleTimer.Start();
[string]$path = $ModuleList[$module];
[hashtable]$ModuleResult = @{};
$moduleConfig = $null;
if ($Config -ne $null -AND $Config.$module -ne $null) {
$moduleConfig = $Config.$module;
}
# First test if the specified module is available
if (Test-Path ($path)) {
try {
# If it is, execute the script and return the output
$ModuleResult.Add('output', (&$path -Config $moduleConfig));
$ModuleResult.Add('response', 200);
$ModuleResult.Add('error', $null);
} catch {
# In case the script we tried to execute runs into a failure, return the exception message as result
$ModuleResult.Add('output', $null);
$ModuleResult.Add('response', 500);
$ModuleResult.Add('error', [string]::Format('Failed to execute module "{0}". Exeception: {1}', $module, $_.Exception.Message));
}
} else {
# Include the module to our output with a small notify message
$ModuleResult.Add('output', $null);
$ModuleResult.Add('response', 404);
$ModuleResult.Add('error', 'Module not found');
}
$ModuleResult.Add('execution', $ModuleTimer.Elapsed.TotalSeconds);
$ModuleTimer.Stop();
$ResultList | Add-Member -Name $module -Type NoteProperty -Value $ModuleResult;
}
return $ResultList;
}
return ClassMonitoring -Include $Include -Exclude $Exclude -ListModules $ListModules -Config $Config -AgentRoot $AgentRoot;

View file

@ -1,577 +0,0 @@
param(
[string]$Counter = '',
[string]$ListCounter = '',
[array]$CounterArray = @(),
[boolean]$ListCategories = $FALSE,
[boolean]$SkipWait = $FALSE,
# These arguments apply to CreateStructuredPerformanceCounterTable
# This is the category name we want to create a structured output
# Example: 'Network Interface'
[string]$CreateStructuredOutputForCategory = '',
# This is the hashtable of Performance Counters, created by
# PerformanceCounterArray
[hashtable]$StructuredCounterInput = @{},
# This argument is just a helper to replace certain strings within
# a instance name with simply nothing.
# Example: 'HarddiskVolume1' => '1'
[array]$StructuredCounterInstanceCleanup = @()
);
# This is our internal cache for Performance Counters already loaded
# In case the Icinga Agent is running as daemon, this hashtable is
# already initialised at the beginning. But if we run the Agent
# from the Powershell directly, we will require to build this cache
# within the environment to work properly and to receive valid data
if ($Icinga2.Cache.PerformanceCounter -eq $null) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
'Creating new performance counter cache'
);
$Icinga2.Cache.PerformanceCounter = @{};
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format(
'Performance Counter Cache content {0}',
($Icinga2.Cache.PerformanceCounter | Out-String)
)
);
<#
# This function will provide a virtual object, containing an array
# of Performance Counters. The object has the following members:
# Name
# Value
# This will ensure we will not have to worry about looping an array
# of mutltiple instances within a counter handler, because this
# function will deal with everything, returning an hashtable
# containing the parent counter name including the values and
# samples for every single instance
#>
function PerformanceCounterArray()
{
param(
[string]$FullName = '',
[array]$PerformanceCounters = @()
);
$pc_instance = New-Object -TypeName PSObject;
$pc_instance | Add-Member -membertype NoteProperty -name 'FullName' -value $FullName;
$pc_instance | Add-Member -membertype NoteProperty -name 'Counters' -value $PerformanceCounters;
$pc_instance | Add-Member -membertype ScriptMethod -name 'Name' -value {
return $this.FullName;
}
$pc_instance | Add-Member -membertype ScriptMethod -name 'Value' -value {
[hashtable]$CounterResults = @{};
foreach ($counter in $this.Counters) {
$CounterResults.Add($counter.Name(), $counter.Value());
}
return $CounterResults;
}
return $pc_instance;
}
<#
# This function will create a custom Performance Counter object with
# already initialised counters, which can be accessed with the
# following members:
# Name
# Value
# Like the PerformanceCounterArray, this will allow to fetch the
# current values of a single counter instance including the name
# of the counter. Within the PerformanceCounterArray function,
# objects created by this function are used.
#>
function PerformanceCounterObject()
{
param(
[string]$FullName = '',
[string]$Category = '',
[string]$Instance = '',
[string]$Counter = '',
[boolean]$SkipWait = $FALSE
);
$pc_instance = New-Object -TypeName PSObject;
$pc_instance | Add-Member -membertype NoteProperty -name 'FullName' -value $FullName;
$pc_instance | Add-Member -membertype NoteProperty -name 'Category' -value $Category;
$pc_instance | Add-Member -membertype NoteProperty -name 'Instance' -value $Instance;
$pc_instance | Add-Member -membertype NoteProperty -name 'Counter' -value $Counter;
$pc_instance | Add-Member -membertype NoteProperty -name 'PerfCounter' -value $Counter;
$pc_instance | Add-Member -membertype NoteProperty -name 'SkipWait' -value $SkipWait;
$pc_instance | Add-Member -membertype ScriptMethod -name 'Init' -value {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format('Creating new Counter for Category {0} with Instance {1} and Counter {2}. Full Name "{3}"',
$this.Category,
$this.Instance,
$this.Counter,
$this.FullName
)
);
# Create the Performance Counter object we want to access
$this.PerfCounter = New-Object System.Diagnostics.PerformanceCounter;
$this.PerfCounter.CategoryName = $this.Category;
$this.PerfCounter.CounterName = $this.Counter;
# Only add an instance in case it is defined
if ([string]::IsNullOrEmpty($this.Instance) -eq $FALSE) {
$this.PerfCounter.InstanceName = $this.Instance
}
# Initialise the counter
try {
$this.PerfCounter.NextValue() | Out-Null;
} catch {
# Nothing to do here, will be handled later
}
<#
# For some counters we require to wait a small amount of time to receive proper data
# Other counters do not need these informations and we do also not require to wait
# for every counter we use, once the counter is initialised within our environment.
# This will allow us to skip the sleep to speed up loading counters
#>
if ($this.SkipWait -eq $FALSE) {
Start-Sleep -Milliseconds 500;
}
}
# Return the name of the counter as string
$pc_instance | Add-Member -membertype ScriptMethod -name 'Name' -value {
return $this.FullName;
}
<#
# Return a hashtable containting the counter value including the
# Sample values for the counter itself. In case we run into an error,
# keep the counter construct but add an error message in addition.
#>
$pc_instance | Add-Member -membertype ScriptMethod -name 'Value' -value {
[hashtable]$CounterData = @{};
try {
[string]$CounterType = $this.PerfCounter.CounterType;
$CounterData.Add('value', $this.PerfCounter.NextValue());
$CounterData.Add('sample', $this.PerfCounter.NextSample());
$CounterData.Add('help', $this.PerfCounter.CounterHelp);
$CounterData.Add('type', $CounterType);
$CounterData.Add('error', $null);
} catch {
$CounterData = @{};
$CounterData.Add('value', $null);
$CounterData.Add('sample', $null);
$CounterData.Add('help', $null);
$CounterData.Add('type', $null);
$CounterData.Add('error', $_.Exception.Message);
}
return $CounterData;
}
# Initialiste the entire counter and internal handlers
$pc_instance.Init();
# Return this custom object
return $pc_instance;
}
<#
# If some informations are missing, it could happen that
# we are unable to create a Performance Counter.
# In this case we will use this Null Object, containing
# the same member functions but allowing us to maintain
# stability without unwanted exceptions
#>
function PerformanceCounterNullObject()
{
param(
[string]$FullName = '',
[string]$ErrorMessage = ''
);
$pc_instance = New-Object -TypeName PSObject;
$pc_instance | Add-Member -membertype NoteProperty -name 'FullName' -value $FullName;
$pc_instance | Add-Member -membertype NoteProperty -name 'ErrorMessage' -value $ErrorMessage;
$pc_instance | Add-Member -membertype ScriptMethod -name 'Name' -value {
return $this.FullName;
}
$pc_instance | Add-Member -membertype ScriptMethod -name 'Value' -value {
[hashtable]$ErrorMessage = @{};
$ErrorMessage.Add('value', $null);
$ErrorMessage.Add('sample', $null);
$ErrorMessage.Add('help', $null);
$ErrorMessage.Add('type', $null);
$ErrorMessage.Add('error', $this.ErrorMessage);
return $ErrorMessage;
}
return $pc_instance;
}
<#
# This function will make monitoring an entire list of
# Performance counters even more easier. We simply provide
# an array of Performance Counters to this module
# and we will receive a construct-save result of an
# hashtable with all performance counters including
# the corresponding values. In that case the code
# size decreases for larger modules.
# Example:
$counter = Get-Icinga-Counter -CounterArray @(
'\Memory\Available Bytes',
'\Memory\% Committed Bytes In Use'
);
#>
function CreatePerformanceCounterResult()
{
param(
[array]$CounterArray = @()
)
[hashtable]$CounterResult = @{};
[bool]$RequireSleep = $FALSE;
foreach ($counter in $CounterArray) {
# We want to speed up things with loading, so we will check if a specified
# Counter is already cached within our hashtable. If it is not, we sleep
# at the end of the function the required 500ms and don't have to wait
# NumOfCounters * 500 milliseconds for the first runs. This will speed
# up the general loading of counters and will not require some fancy
# pre-caching / configuration handler
if ($Icinga2.Cache.PerformanceCounter -ne $null) {
if ($Icinga2.Cache.PerformanceCounter.ContainsKey($counter) -eq $FALSE) {
$RequireSleep = $TRUE;
}
}
$obj = CreatePerformanceCounter -Counter $counter -SkipWait $TRUE;
if ($CounterResult.ContainsKey($obj.Name()) -eq $FALSE) {
$CounterResult.Add($obj.Name(), $obj.Value());
}
}
# Above we initialse ever single counter and we only require a sleep once
# in case a new, yet unknown counter was added
if ($RequireSleep) {
Start-Sleep -Milliseconds 500;
# Agreed, this is some sort of code duplication but it wouldn't make
# any sense to create a own function for this. Why are we doing
# this anway?
# Simple: In case we found counters which have yet not been initialised
# we did this above. Now we have waited 500 ms to receive proper
# values from these counters. As the previous generated result
# might have contained counters with 0 results, we will now
# check all counters again to receive the proper values.
# Agreed, might sound like a overhead, but the impact only
# applies to the first call of the module with the counters.
# This 'duplication' however decreased the execution from
# certain modules from 25s to 1s on the first run. Every
# additional run is then beeing executed within 0.x s
# which sounds like a very good performance and solution
$CounterResult = @{};
foreach ($counter in $CounterArray) {
$obj = CreatePerformanceCounter -Counter $counter -SkipWait $TRUE;
if ($CounterResult.ContainsKey($obj.Name()) -eq $FALSE) {
$CounterResult.Add($obj.Name(), $obj.Value());
}
}
}
return $CounterResult;
}
<#
# This is the main function which is called from this script, constructing our counters
# and loading possible sub-instances from our Performance Counter.
# It will return either an PerformanceCounterObject or PerformanceCounterArray
# which both contain the same members, allowing us to dynamicly use the objects
# without having to worry about exception.
#>
function CreatePerformanceCounter()
{
param(
[string]$Counter = '',
[boolean]$SkipWait = $FALSE
);
# Simply use the counter name, like
# \Paging File(_total)\% Usage
if ([string]::IsNullOrEmpty($Counter) -eq $TRUE) {
return (PerformanceCounterNullObject -FullName $Counter -ErrorMessage 'Failed to initialise counter, as no counter was specified.');
}
[array]$CounterArray = $Counter.Split('\');
[string]$UseCounterCategory = '';
[string]$UseCounterName = '';
[string]$UseCounterInstance = '';
# If we add the counter as it should be
# \Paging File(_total)\% Usage
# the first array element will be an empty string we can skip
# Otherwise the name was wrong and we should not continue
if (-Not [string]::IsNullOrEmpty($CounterArray[0])) {
return (PerformanceCounterNullObject -FullName $Counter -ErrorMessage ([string]::Format('Failed to deserialize counter "{0}". It seems the leading "\" is missing.', $Counter)));
}
# In case our Performance Counter is containing instances, we should split
# The content and read the instance and counter category out
if ($CounterArray[1].Contains('(')) {
[array]$TmpCounter = $CounterArray[1].Split('(');
$UseCounterCategory = $TmpCounter[0];
$UseCounterInstance = $TmpCounter[1].Replace(')', '');
} else {
# Otherwise we only require the category
$UseCounterCategory = $CounterArray[1];
}
# At last get the actual counter containing our values
$UseCounterName = $CounterArray[2];
# Now as we know how the counter path is constructed and has been splitted into
# the different values, we need to know how to handle the instances of the counter
# If we specify a instance with (*) we want the module to automaticly fetch all
# instances for this counter. This will result in an PerformanceCounterArray
# which contains the parent name including counters for all instances that
# have been found
if ($UseCounterInstance -eq '*') {
# In case we already loaded the counters once, return the finished array
if ($Icinga2.Cache.PerformanceCounter.ContainsKey($Counter) -eq $TRUE) {
return (PerformanceCounterArray -FullName $Counter -PerformanceCounters $Icinga2.Cache.PerformanceCounter[$Counter]);
}
# If we need to build the array, load all instances from the counters and
# create single performance counters and add them to a custom array and
# later to a custom object
try {
[array]$AllCountersIntances = @();
$CounterInstances = New-Object System.Diagnostics.PerformanceCounterCategory($UseCounterCategory);
foreach ($instance in $CounterInstances.GetInstanceNames()) {
[string]$NewCounterName = $Counter.Replace('*', $instance);
$NewCounter = PerformanceCounterObject -FullName $NewCounterName -Category $UseCounterCategory -Counter $UseCounterName -Instance $instance -SkipWait $SkipWait;
$AllCountersIntances += $NewCounter;
}
} catch {
return (PerformanceCounterNullObject -FullName $Counter -ErrorMessage ([string]::Format('Failed to deserialize instances for counter "{0}". Exception: "{1}".', $Counter, $_.Exception.Message)));
}
# Add the parent counter including the array of Performance Counters to our
# caching mechanism and return the PerformanceCounterArray object for usage
# within the monitoring modules
$Icinga2.Cache.PerformanceCounter.Add($Counter, $AllCountersIntances);
return (PerformanceCounterArray -FullName $Counter -PerformanceCounters $AllCountersIntances);
} else {
# This part will handle the counters without any instances as well as
# specificly assigned instances, like (_Total) CPU usage.
# In case we already have the counter within our cache, return the
# cached informations
if ($Icinga2.Cache.PerformanceCounter.ContainsKey($Counter) -eq $TRUE) {
return $Icinga2.Cache.PerformanceCounter[$Counter];
}
# If the cache is not present yet, create the Performance Counter object,
# and add it to our cache
$NewCounter = PerformanceCounterObject -FullName $Counter -Category $UseCounterCategory -Counter $UseCounterName -Instance $UseCounterInstance -SkipWait $SkipWait;
$Icinga2.Cache.PerformanceCounter.Add($Counter, $NewCounter);
}
# This function will always return non-instance counters or
# specificly defined instance counters. Performance Counter Arrays
# are returned within their function. This is just to ensure that the
# function looks finished from developer point of view
return $Icinga2.Cache.PerformanceCounter[$Counter];
}
#
# This function will get handy in case we want to fetch Counters
# which have instances which might be helpful to group by their
# instances name. This will apply to Disk and Network Interface
# outputs for example, as it would be helpful to combine all
# counter results for a specific disk / interface in one
# result for easier working with these informations
#
function CreateStructuredPerformanceCounterTable
{
param(
[string]$CounterCategory = '',
[hashtable]$PerformanceCounterHash = @{},
[array]$InstanceNameCleanupArray = @()
)
# The storage variables we require to store our data
[array]$AvailableInstances = @();
[hashtable]$StructuredCounterData = @{};
# With this little trick we can fetch all instances we have and get their unique name
$CounterInstances = New-Object System.Diagnostics.PerformanceCounterCategory($CounterCategory);
foreach ($instance in $CounterInstances.GetInstanceNames()) {
# For some counters we require to apply a 'cleanup' for the instance name
# Example Disks: Some disks are stored with the name
# 'HarddiskVolume1'
# To be able to map the volume correctly to disks, we require to remove
# 'HarddiskVolume' so only '1' will remain, which allows us to map the
# volume correctly afterwards
[string]$CleanInstanceName = $instance;
foreach ($cleanup in $InstanceNameCleanupArray) {
$CleanInstanceName = $CleanInstanceName.Replace($cleanup, '');
}
$AvailableInstances += $CleanInstanceName;
}
# Now let the real magic begin.
# At first we will loop all instances of our Performance Counters, which means all
# instances we have found above. We build a new hashtable then to list the instances
# by their individual name and all corresponding counters as children
# This allows us a structured output with all data for each instance
foreach ($instance in $AvailableInstances) {
# First build a hashtable for each instance to add data to later
$StructuredCounterData.Add($instance, @{});
# Now we need to loop all return values from our Performance Counters
foreach ($InterfaceCounter in $PerformanceCounterHash.Keys) {
# As we just looped the parent counter (Instance *), we now need to
# loop the actual counters for each instance
foreach ($interface in $PerformanceCounterHash[$InterfaceCounter]) {
# Finally let's loop through all the results which contain the values
# to build our new, structured hashtable
foreach ($entry in $interface.Keys) {
# Match the counters based on our current parent index
# (the instance name we want to add the values as children).
if ($entry.Contains('(' + $instance + ')')) {
# To ensure we don't transmit the entire counter name,
# we only want to include the name of the actual counter.
# There is no need to return
# \Network Interface(Desktopadapter Intel[R] Gigabit CT)\Bytes Received/sec
# the naming
# Bytes Received/sec
# is enough
[array]$TmpOutput = $entry.Split('\');
[string]$OutputName = $TmpOutput[$TmpOutput.Count - 1];
# Now add the actual value to our parent instance with the
# improved value name, including the sample and counter value data
$StructuredCounterData[$instance].Add($OutputName, $interface[$entry]);
}
}
}
}
}
return $StructuredCounterData;
}
#
# This function will load all available Categories of Performance Counters
# from the registry and outputs them. This will ensure we can fetch the real
# english names instead of the localiced ones
#
function ListCounterCategories()
{
$RegistryData = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009' `
-Name 'counter' | Select-Object -ExpandProperty Counter;
[array]$Counters = @();
# Now lets loop our registry data and fetch only for counter categories
# Ignore everything else and drop the information
foreach ($counter in $RegistryData) {
# First filter out the ID's of the performance counter
if (-Not ($counter -match "^[\d\.]+$") -And [string]::IsNullOrEmpty($counter) -eq $FALSE) {
# Now check if the value we got is a counter category
if ([System.Diagnostics.PerformanceCounterCategory]::Exists($counter) -eq $TRUE) {
$Counters += $counter;
}
}
}
return $Counters;
}
#
# Provide the name of a category to fetch all available counters and
# if there are any instances assigned to it
#
function ListCountersFromCategory()
{
param ([string]$CounterCategory);
[hashtable]$counters = @{};
try {
# At first create our Performance Counter object for the category we specified
$Category = New-Object System.Diagnostics.PerformanceCounterCategory($CounterCategory);
# Now loop through all keys to find the name of available counters
foreach ($counter in $Category.ReadCategory().Keys) {
[string]$CounterInstanceAddition = '';
# As counters might also have instances (like interfaces, disks, paging file), we should
# try to load them as well
foreach ($instance in $Category.ReadCategory()[$counter].Keys) {
# If we do not match this magic string, we have multiple instances we can access
# to get informations for different disks, volumes and interfaces for example
if ($instance -ne 'systemdiagnosticsperfcounterlibsingleinstance') {
# Re-Write the name we return of the counter to something we can use directly
# within our modules to load data from. A returned counter will look like this
# for example:
# \PhysicalDisk(*)\avg. disk bytes/read
[string]$UsableCounterName = [string]::Format('\{0}(*)\{1}', $CounterCategory, $counter);
if ($counters.ContainsKey($UsableCounterName) -eq $TRUE) {
$counters[$UsableCounterName] += $Category.ReadCategory()[$counter][$instance];
} else {
$counters.Add($UsableCounterName, @( $Category.ReadCategory()[$counter][$instance] ));
}
} else {
# For counters with no instances, we still require to return a re-build Performance Counter
# output, to make later usage in our modules very easy. This can look like this:
# \System\system up time
[string]$UsableCounterName = [string]::Format('\{0}\{1}', $CounterCategory, $counter);
$counters.Add($UsableCounterName, $null);
}
}
};
} catch {
# In case we run into an error, return an error message
$counters.Add('error', $_.Exception.Message);
}
return $counters;
}
if ([string]::IsNullOrEmpty($CreateStructuredOutputForCategory) -eq $FALSE) {
return (CreateStructuredPerformanceCounterTable `
-CounterCategory $CreateStructuredOutputForCategory `
-PerformanceCounterHash $StructuredCounterInput `
-InstanceNameCleanupArray $StructuredCounterInstanceCleanup
)
}
if ($ListCategories -eq $TRUE) {
return ListCounterCategories;
}
if ([string]::IsNullOrEmpty($ListCounter) -eq $FALSE) {
return ListCountersFromCategory -CounterCategory $ListCounter;
}
# Make things easier by simply proividing an array of Performance Counter
# Names we wish to monitor
if ($CounterArray.Count -ne 0) {
return (CreatePerformanceCounterResult -CounterArray $CounterArray);
}
return CreatePerformanceCounter -Counter $Counter -SkipWait $SkipWait;

View file

@ -1,97 +0,0 @@
param(
[bool]$IsAgentIntalled = $FALSE
)
function ClassSetup()
{
param(
[bool]$IsAgentIntalled = $FALSE
);
$instance = New-Object -TypeName PSObject;
$instance | Add-Member -membertype NoteProperty -name 'BaseDirectory' -value (Join-Path $Icinga2.App.RootPath -ChildPath 'agent');
$instance | Add-Member -membertype ScriptMethod -name 'Init' -value {
$IsInstalled = Get-Icinga-Config -Key 'setup.installed';
if ($IsAgentIntalled) {
if ($IsInstalled -eq $FALSE -Or $IsInstalled -eq $null) {
return 0;
}
}
$this.CreateDirectories('config');
$this.CreateDirectories('state');
if ($IsInstalled -eq $FALSE -Or $IsInstalled -eq $null) {
$this.InstallEventLog();
$this.CreateConfig();
}
# At this point for this module, we require to return 1 as 'true'
return 1;
}
$instance | Add-Member -membertype ScriptMethod -name 'CreateDirectories' -value {
param([string]$directory);
[string]$path = Join-Path $this.BaseDirectory -ChildPath $directory;
if (-Not (Test-Path $path)) {
New-Item $path -ItemType Directory | Out-Null;
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
([string]::Format('Creating new directory "{0}"', $path))
);
}
}
$instance | Add-Member -membertype ScriptMethod -name 'InstallEventLog' -value {
try {
New-EventLog -LogName Application -Source ($Icinga2.Service.servicedisplayname) -ErrorAction Stop;
$Icinga2.Log.WriteConsole(
$Icinga2.Enums.LogState.Info,
[string]::Format(
'Successfully installed EventLog "{0}" for this module',
$Icinga2.Service.servicedisplayname
)
);
} catch {
$Icinga2.Log.WriteConsole(
$Icinga2.Enums.LogState.Warning,
[string]::Format(
'EventLog for "{0}" is already installed.',
$Icinga2.Service.servicedisplayname
)
);
}
}
$instance | Add-Member -membertype ScriptMethod -name 'CreateConfig' -value {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Info,
'### Installing default configuration values ###'
);
Set-Icinga-Config -Key 'checker.server.host' -Value 'https://localhost/icingaweb2/windows/checkresult' | Out-Null;
Set-Icinga-Config -Key 'checker.ssl.verify' -Value $TRUE | Out-Null;
Set-Icinga-Config -Key 'tcp.socket.host' -Value 'localhost' | Out-Null;
Set-Icinga-Config -Key 'tcp.socket.port' -Value '5891' | Out-Null;
Set-Icinga-Config -Key 'service.name' -Value 'icinga2winservice' | Out-Null;
Set-Icinga-Config -Key 'service.displayname' -Value 'Icinga 2 Windows Service' | Out-Null;
Set-Icinga-Config -Key 'setup.installed' -Value $TRUE | Out-Null;
Set-Icinga-Config -Key 'certstore.name' -Value 'My' | Out-Null;
Set-Icinga-Config -Key 'certstore.location' -Value 'LocalMachine' | Out-Null;
Set-Icinga-Config -Key 'certstore.certificate.name' -Value '' | Out-Null;
Set-Icinga-Config -Key 'certstore.certificate.thumbprint' -Value '' | Out-Null;
Set-Icinga-Config -Key 'logger.directory' -Value '' | Out-Null;
Set-Icinga-Config -Key 'logger.debug' -Value $FALSE | Out-Null;
Set-Icinga-Config -Key 'authentication.enabled' -Value $FALSE | Out-Null;
Set-Icinga-Config -Key 'authentication.user' -Value '' | Out-Null;
Set-Icinga-Config -Key 'authentication.domain' -Value '' | Out-Null;
}
return $instance.Init();
}
return ClassSetup -IsAgentIntalled $IsAgentIntalled;

View file

@ -1,21 +0,0 @@
function ClassBIOS
{
# Lets load some bios informations
$BIOSInformation = Get-CimInstance Win32_BIOS;
[hashtable]$BIOSData = @{};
foreach ($bios_properties in $BIOSInformation) {
#$bios_datails = @{};
foreach($bios in $bios_properties.CimInstanceProperties) {
#$bios_datails.Add($bios.Name, $bios.Value);
$BIOSData.Add($bios.Name, $bios.Value);
}
#$BIOSData.Add($bios_datails.DeviceID, $bios_datails);
}
return $BIOSData;
}
return ClassBIOS;

View file

@ -1,112 +0,0 @@
param($Config = $null);
function ClassCertificates()
{
param($Config = $null);
[hashtable]$CertStore = @{};
[hashtable]$CertLocation = @{};
[hashtable]$CertCounters = @{};
Set-Location 'cert:' | Out-Null;
$certs = Get-ChildItem -Recurse;
foreach ($cert in $certs) {
if ($cert.LocationName) {
if ($CertStore.ContainsKey($cert.LocationName) -eq $FALSE) {
$CertStore.Add($cert.LocationName, @{});
}
}
if ($cert.IssuerName) {
[hashtable]$Certificate = @{};
$Certificate.Add('Archived', $cert.Archived);
$Certificate.Add('HasPrivateKey', $cert.HasPrivateKey);
$Certificate.Add('IssuerName.Name', $cert.IssuerName.Name);
$Certificate.Add('IssuerName.Oid', $cert.IssuerName.Oid);
$Certificate.Add('NotAfter', $cert.NotAfter);
$Certificate.Add('NotBefore', $cert.NotBefore);
$Certificate.Add('SerialNumber', $cert.SerialNumber);
$Certificate.Add('SubjectName.Name', $cert.SubjectName.Name);
$Certificate.Add('SubjectOid.Oid', $cert.SubjectName.Oid);
$Certificate.Add('SignatureAlgorithm.Value', $cert.SignatureAlgorithm.Value);
$Certificate.Add('SignatureAlgorithm.FriendlyName', $cert.SignatureAlgorithm.FriendlyName);
$Certificate.Add('Thumbprint', $cert.Thumbprint);
$Certificate.Add('Version', $cert.Version);
$Certificate.Add('Issuer', $cert.Issuer);
$Certificate.Add('Subject', $cert.Subject);
$Certificate.Add('PSParentPath', $cert.PSParentPath);
$Certificate.Add('PSChildName', $cert.PSChildName);
$Certificate.Add('DnsNameList', $cert.DnsNameList);
[string]$cert_store = (GetCertStore -CertPath $cert.PSPath);
[string]$cert_location = (GetCertLocation -CertPath $cert.PSPath);
$Certificate.Add('CertStore', $cert_store);
$Certificate.Add('CertLocation', $cert_location);
if ($CertLocation.ContainsKey($cert_location)) {
$CertLocation[$cert_location] += $Certificate;
} else {
$CertLocation.Add($cert_location, @( $Certificate ));
}
}
}
foreach ($cert_arr in $CertLocation.Keys) {
foreach ($cert in $CertLocation[$cert_arr]) {
[string]$CertFullPathCache = [string]::Format(
'{0}\{1}\{2}',
$cert.CertStore,
$cert.CertLocation,
$cert.Thumbprint
);
if ($CertCounters.ContainsKey($CertFullPathCache) -eq $FALSE) {
$CertCounters.Add($CertFullPathCache, 1);
} else {
$CertCounters[$CertFullPathCache] += 1;
}
if ($CertStore[$cert.CertStore].ContainsKey($cert.CertLocation)) {
[string]$CertThumbprintKey = $cert.Thumbprint;
if ($CertCounters[$CertFullPathCache] -gt 1) {
$CertThumbprintKey = [string]::Format(
'{0} ({1})',
$CertThumbprintKey,
$CertCounters[$CertFullPathCache]
);
}
$CertStore[$cert.CertStore][$cert.CertLocation].Add($CertThumbprintKey, $cert);
} else {
$CertStore[$cert.CertStore].Add($cert.CertLocation, @{ $cert.Thumbprint = $cert });
}
}
}
return $CertStore
}
function GetCertStore()
{
param([string]$CertPath);
$CertPath = $CertPath.Replace('Microsoft.PowerShell.Security\', '');
$CertPath = $CertPath.Replace('Certificate::', '');
[array]$path = $CertPath.Split('\');
return $path[0];
}
function GetCertLocation()
{
param([string]$CertPath);
$CertPath = $CertPath.Replace('Microsoft.PowerShell.Security\', '');
$CertPath = $CertPath.Replace('Certificate::', '');
[array]$path = $CertPath.Split('\');
return $path[1];
}
return ClassCertificates -Config $Config;

View file

@ -1,18 +0,0 @@
param($Config = $null);
function ClassCPU
{
param($Config = $null);
# This will return a hashtable with every single counter
# We specify within the array
$counter = Get-Icinga-Counter -CounterArray @(
'\Processor(*)\% Processor Time',
'\System\Processor Queue Length',
'\System\Threads'
);
return $counter;
}
return ClassCPU -Config $Config;

View file

@ -1,96 +0,0 @@
param($Config = $null);
function ClassDisk()
{
param($Config = $null);
# The storage variables we require to store our data
[hashtable]$StructuredDiskData = @{};
# This will return a hashtable with every single counter
# we specify within the array. Instead of returning all
# the values in the returned hashtable, we will rebuild
# the result a little to have a improved output which
# is more user friendly and allows us to check for
# certain disks / volumes in details with a simpler
# accessing possibility
$counter = Get-Icinga-Counter -CounterArray @(
'\PhysicalDisk(*)\% Disk Read Time',
'\PhysicalDisk(*)\Current Disk Queue Length',
'\PhysicalDisk(*)\Avg. Disk Bytes/Transfer',
'\PhysicalDisk(*)\Split IO/sec',
'\PhysicalDisk(*)\Disk Reads/sec',
'\PhysicalDisk(*)\Disk Writes/sec',
'\PhysicalDisk(*)\Disk Bytes/sec',
'\PhysicalDisk(*)\Avg. Disk Read Queue Length',
'\PhysicalDisk(*)\Avg. Disk sec/Write',
'\PhysicalDisk(*)\% Disk Time',
'\PhysicalDisk(*)\Avg. Disk sec/Transfer',
'\PhysicalDisk(*)\Avg. Disk Bytes/Write',
'\PhysicalDisk(*)\% Disk Write Time',
'\PhysicalDisk(*)\Avg. Disk Queue Length',
'\PhysicalDisk(*)\Disk Write Bytes/sec',
'\PhysicalDisk(*)\Avg. Disk sec/Read',
'\PhysicalDisk(*)\Disk Read Bytes/sec',
'\PhysicalDisk(*)\Disk Transfers/sec',
'\PhysicalDisk(*)\% Idle Time',
'\PhysicalDisk(*)\Avg. Disk Write Queue Length',
'\PhysicalDisk(*)\Avg. Disk Bytes/Read'
);
$logicalCounter = Get-Icinga-Counter -CounterArray @(
'\LogicalDisk(*)\Free Megabytes',
'\LogicalDisk(*)\% Free Space'
);
# This function will help us to build a structured output based on
# volumes / disks found within the instances. We will use our
# LogicalDisk as 'index' to assign our performance Counters to.
# In addition we then provide the hashtable of counters we fetched
# above. Last but not least we cleanup the instances name to replace
# 'HarddiskVolume1' for '1' for example, to ensure the mapping of disk
# informations is working as intended
[hashtable]$DiskData = Get-Icinga-Counter `
-CreateStructuredOutputForCategory 'PhysicalDisk' `
-StructuredCounterInput $counter;
foreach ($counters in $logicalCounter.Keys) {
foreach ($counter in $logicalCounter[$counters].Keys) {
[string]$instance = $counter;
if ($instance.Contains('(') -And $instance.Contains(')')) {
[int]$bracketStart = $instance.IndexOf('(') + 1;
[int]$bracketEnd = $instance.IndexOf(')');
$instance = $instance.Substring($bracketStart, $bracketEnd - $bracketStart);
$instanceArray = $counter.Split('\');
$counterName = $instanceArray[$instanceArray.Length - 1];
foreach ($disk in $DiskData.Keys) {
if ($disk.Contains($instance)) {
$DiskData[$disk].Add(
$counterName,
$logicalCounter[$counters][$counter]
);
}
}
}
}
}
# Rewrite our output a little to make it more user friendly
# This is unique for disks, as we want to remove the ':' from
# Drive Letters and add back the HarddiskVolume label to volumes
# to prevent having only a numeric table keys. Example:
# '1' => 'HarddiskVolume1'
foreach ($disk in $DiskData.Keys) {
$NewKey = $disk.Replace(':', '');
if ($NewKey -match "^[\d\.]+$") {
$NewKey = [string]::Format('HarddiskVolume{0}', $NewKey);
}
if ($NewKey[0] -match "^[\d\.]+$") {
$NewKey = $NewKey.Substring(2, $NewKey.Length - 2);
}
$StructuredDiskData.Add($NewKey, $DiskData[$disk]);
}
return $StructuredDiskData;
}
return ClassDisk -Config $Config;

View file

@ -1,6 +0,0 @@
param($Config = $null);
return $Icinga2.Utils.Modules.LoadIncludes(
$MyInvocation.MyCommand.Name,
$Config
);

View file

@ -1,19 +0,0 @@
param($Config = $null);
#
# Fetch the CPU Hardware informations
#
# Lets load some additional CPU informations, besides current performance counters
# It might be useful to get more details about the hardware itself
$CPUInformations = Get-CimInstance Win32_Processor;
[hashtable]$PhysicalCPUData = @{};
foreach ($cpu_properties in $CPUInformations) {
$cpu_datails = @{};
foreach($cpu_core in $cpu_properties.CimInstanceProperties) {
$cpu_datails.Add($cpu_core.Name, $cpu_core.Value);
}
$PhysicalCPUData.Add($cpu_datails.DeviceID, $cpu_datails);
}
return $PhysicalCPUData;

View file

@ -1,70 +0,0 @@
param($Config = $null);
#
# Fetch the Disk Hardware informations
#
# Lets load some additional disk informations, besides current data
# It might be useful to get more details about the hardware itself
$DisksInformations = Get-CimInstance Win32_DiskDrive;
[hashtable]$PhysicalDiskData = @{};
foreach ($disk_properties in $DisksInformations) {
$disk_datails = @{};
foreach($disk in $disk_properties.CimInstanceProperties) {
$disk_datails.Add($disk.Name, $disk.Value);
}
$disk_datails.Add('DriveReference', @());
$PhysicalDiskData.Add($disk_datails.DeviceID, $disk_datails);
}
$DiskPartitionInfo = Get-WmiObject Win32_DiskDriveToDiskPartition;
[hashtable]$MapDiskPartitionToLogicalDisk = @{};
foreach ($item in $DiskPartitionInfo) {
[string]$diskPartition = $item.Dependent.SubString(
$item.Dependent.LastIndexOf('=') + 1,
$item.Dependent.Length - $item.Dependent.LastIndexOf('=') - 1
);
$diskPartition = $diskPartition.Replace('"', '');
[string]$physicalDrive = $item.Antecedent.SubString(
$item.Antecedent.LastIndexOf('\') + 1,
$item.Antecedent.Length - $item.Antecedent.LastIndexOf('\') - 1
)
$physicalDrive = $physicalDrive.Replace('"', '');
$MapDiskPartitionToLogicalDisk.Add($diskPartition, $physicalDrive);
}
$LogicalDiskInfo = Get-WmiObject Win32_LogicalDiskToPartition;
foreach ($item in $LogicalDiskInfo) {
[string]$driveLetter = $item.Dependent.SubString(
$item.Dependent.LastIndexOf('=') + 1,
$item.Dependent.Length - $item.Dependent.LastIndexOf('=') - 1
);
$driveLetter = $driveLetter.Replace('"', '');
[string]$diskPartition = $item.Antecedent.SubString(
$item.Antecedent.LastIndexOf('=') + 1,
$item.Antecedent.Length - $item.Antecedent.LastIndexOf('=') - 1
)
$diskPartition = $diskPartition.Replace('"', '');
if ($MapDiskPartitionToLogicalDisk.ContainsKey($diskPartition)) {
foreach ($disk in $PhysicalDiskData.Keys) {
[string]$DiskId = $disk.SubString(
$disk.LastIndexOf('\') + 1,
$disk.Length - $disk.LastIndexOf('\') - 1
);
if ($DiskId.ToLower() -eq $MapDiskPartitionToLogicalDisk[$diskPartition].ToLower()) {
$PhysicalDiskData[$disk]['DriveReference'] += $driveLetter;
}
}
}
}
return $PhysicalDiskData;

View file

@ -1,59 +0,0 @@
param($Config = $null);
#
# Fetch the Memory Hardware informations
#
# Lets load some additional memory informations, besides current performance counters
# It might be useful to get more details about the hardware itself
$MemoryInformations = Get-CimInstance Win32_PhysicalMemory;
$capacity = $MemoryInformations | Measure-Object -Property capacity -Sum;
# Lets load the details from our RAM modules
[hashtable]$PhysicalMemoryData = @{};
$PhysicalMemoryData.Add('Modules', $capacity.Count);
foreach($memory_object in $MemoryInformations) {
$memory_datails = @{};
$memory_datails.Add('caption', $memory_object.Caption);
$memory_datails.Add('desc', $memory_object.Description);
$memory_datails.Add('name', $memory_object.Name);
$memory_datails.Add('install_date', $memory_object.InstallDate);
$memory_datails.Add('status', $memory_object.Status);
$memory_datails.Add('creation_class_name', $memory_object.CreationClassName);
$memory_datails.Add('manufacturer', $memory_object.Manufacturer);
$memory_datails.Add('model', $memory_object.Model);
$memory_datails.Add('other_identifiying_info', $memory_object.OtherIdentifyingInfo);
$memory_datails.Add('part_number', $memory_object.PartNumber);
$memory_datails.Add('powered_on', $memory_object.PoweredOn);
$memory_datails.Add('serial_number', $memory_object.SerialNumber);
$memory_datails.Add('sku', $memory_object.SKU);
$memory_datails.Add('tag', $memory_object.Tag);
$memory_datails.Add('version', $memory_object.Version);
$memory_datails.Add('hot_swappable', $memory_object.HotSwappable);
$memory_datails.Add('removable', $memory_object.Removable);
$memory_datails.Add('replaceable', $memory_object.Replaceable);
$memory_datails.Add('form_factor', $memory_object.FormFactor);
$memory_datails.Add('bank_label', $memory_object.BankLabel);
$memory_datails.Add('capacity', $memory_object.Capacity);
$memory_datails.Add('data_width', $memory_object.DataWidth);
$memory_datails.Add('interleave_position', $memory_object.InterleavePosition);
$memory_datails.Add('memory_type', $memory_object.MemoryType);
$memory_datails.Add('position_in_row', $memory_object.PositionInRow);
$memory_datails.Add('speed', $memory_object.Speed);
$memory_datails.Add('total_width', $memory_object.TotalWidth);
$memory_datails.Add('attributes', $memory_object.Attributes);
$memory_datails.Add('configured_clock_speed', $memory_object.ConfiguredClockSpeed);
$memory_datails.Add('configured_voltage', $memory_object.ConfiguredVoltage);
$memory_datails.Add('device_locator', $memory_object.DeviceLocator);
$memory_datails.Add('interleave_data_depth', $memory_object.InterleaveDataDepth);
$memory_datails.Add('max_voltage', $memory_object.MaxVoltage);
$memory_datails.Add('min_voltage', $memory_object.MinVoltage);
$memory_datails.Add('smbios_memory_type', $memory_object.SMBIOSMemoryType);
$memory_datails.Add('type_detail', $memory_object.TypeDetail);
$memory_datails.Add('ps_computer_name', $memory_object.PSComputerName);
$PhysicalMemoryData.Add($memory_object.Tag, $memory_datails);
}
return $PhysicalMemoryData;

View file

@ -1,27 +0,0 @@
param($Config = $null);
[hashtable]$HotfixInfo = @{};
[hashtable]$HotfixNameCache = @{};
# First fetch all of our hotfixes
$Hotfixes = Get-Hotfix;
foreach ($property in $Hotfixes) {
[hashtable]$HotfixData = @{};
foreach ($hotfix in $property.Properties) {
$HotfixData.Add($hotfix.Name, $hotfix.Value);
}
[string]$name = [string]::Format('{0} [{1}]', $HotfixData.HotFixID, $HotfixData.InstalledOn);
if ($HotfixNameCache.ContainsKey($name) -eq $FALSE) {
$HotfixNameCache.Add($name, 1);
} else {
$HotfixNameCache[$name] += 1;
$name = [string]::Format('{0} ({1})', $name, $HotfixNameCache[$name]);
}
$HotfixInfo.Add($name, $HotfixData);
}
return $HotfixInfo;

View file

@ -1,76 +0,0 @@
param($Config = $null);
[hashtable]$PendingUpdates = @{};
[hashtable]$PendingUpdateNameCache = @{};
# Fetch all informations about installed updates and add them
$WindowsUpdates = New-Object -ComObject "Microsoft.Update.Session";
$SearchIndex = $WindowsUpdates.CreateUpdateSearcher();
try {
# Get a list of current pending updates which are not yet installed on the system
$Pending = $SearchIndex.Search("IsInstalled=0");
$PendingUpdates.Add('count', $Pending.Updates.Count);
foreach ($update in $Pending.Updates) {
[hashtable]$PendingUpdateDetails = @{};
$PendingUpdateDetails.Add('Title', $update.Title);
$PendingUpdateDetails.Add('Deadline', $update.Deadline);
$PendingUpdateDetails.Add('Description', $update.Description);
$PendingUpdateDetails.Add('IsBeta', $update.IsBeta);
$PendingUpdateDetails.Add('IsDownloaded', $update.IsDownloaded);
$PendingUpdateDetails.Add('IsHidden', $update.IsHidden);
$PendingUpdateDetails.Add('IsInstalled', $update.IsInstalled);
$PendingUpdateDetails.Add('IsMandatory', $update.IsMandatory);
$PendingUpdateDetails.Add('IsUninstallable', $update.IsUninstallable);
$PendingUpdateDetails.Add('Languages', $update.Languages);
$PendingUpdateDetails.Add('LastDeploymentChangeTime', $update.LastDeploymentChangeTime);
$PendingUpdateDetails.Add('MaxDownloadSize', $update.MaxDownloadSize);
$PendingUpdateDetails.Add('MinDownloadSize', $update.MinDownloadSize);
$PendingUpdateDetails.Add('MoreInfoUrls', $update.MoreInfoUrls);
$PendingUpdateDetails.Add('MsrcSeverity', $update.MsrcSeverity);
$PendingUpdateDetails.Add('RecommendedCpuSpeed', $update.RecommendedCpuSpeed);
$PendingUpdateDetails.Add('RecommendedHardDiskSpace', $update.RecommendedHardDiskSpace);
$PendingUpdateDetails.Add('RecommendedMemory', $update.RecommendedMemory);
$PendingUpdateDetails.Add('ReleaseNotes', $update.ReleaseNotes);
$PendingUpdateDetails.Add('SecurityBulletinIDs', $update.SecurityBulletinIDs);
$PendingUpdateDetails.Add('SupersededUpdateIDs', $update.SupersededUpdateIDs);
$PendingUpdateDetails.Add('SupportUrl', $update.SupportUrl);
$PendingUpdateDetails.Add('Type', $update.Type);
$PendingUpdateDetails.Add('UninstallationNotes', $update.UninstallationNotes);
$PendingUpdateDetails.Add('UninstallationBehavior', $update.UninstallationBehavior);
$PendingUpdateDetails.Add('UninstallationSteps', $update.UninstallationSteps);
$PendingUpdateDetails.Add('KBArticleIDs', $update.KBArticleIDs);
$PendingUpdateDetails.Add('DeploymentAction', $update.DeploymentAction);
$PendingUpdateDetails.Add('DownloadPriority', $update.DownloadPriority);
$PendingUpdateDetails.Add('RebootRequired', $update.RebootRequired);
$PendingUpdateDetails.Add('IsPresent', $update.IsPresent);
$PendingUpdateDetails.Add('CveIDs', $update.CveIDs);
$PendingUpdateDetails.Add('BrowseOnly', $update.BrowseOnly);
$PendingUpdateDetails.Add('PerUser', $update.PerUser);
$PendingUpdateDetails.Add('AutoSelection', $update.AutoSelection);
$PendingUpdateDetails.Add('AutoDownload', $update.AutoDownload);
[string]$name = [string]::Format('{0} [{1}]', $update.Title, $update.LastDeploymentChangeTime);
if ($PendingUpdateNameCache.ContainsKey($name) -eq $FALSE) {
$PendingUpdateNameCache.Add($name, 1);
} else {
$PendingUpdateNameCache[$name] += 1;
$name = [string]::Format('{0} ({1})', $name, $PendingUpdateNameCache[$name]);
}
$PendingUpdates.Add($name, $PendingUpdateDetails);
}
} catch {
if ($PendingUpdates.ContainsKey('Count') -eq $FALSE) {
$PendingUpdates.Add('count', 0);
} else {
$PendingUpdates['count'] = 0;
}
$PendingUpdates.Add('error', [string]::Format(
'Failed to query Windows Update server: {0}',
$_.Exception.Message
));
}
return $PendingUpdates;

View file

@ -1,72 +0,0 @@
param($Config = $null);
# Fetch all informations about installed updates and add them
$WindowsUpdates = New-Object -ComObject "Microsoft.Update.Session";
$SearchIndex = $WindowsUpdates.CreateUpdateSearcher();
[hashtable]$UpdateList = @{};
[hashtable]$UpdateInstalled = @{};
[hashtable]$UpdateUninstalled = @{};
[hashtable]$UpdateOther = @{};
# Operation ID's
# 1: Installed
# 2: Uninstalled
# 3: Other
# At first get a list of our Windows Update history
$Updates = $SearchIndex.QueryHistory(0, $SearchIndex.GetTotalHistoryCount()) |
Select-Object Operation, ResultCode, HResult, Date, Title, Description, ServiceID, SupportUrl;
foreach ($update in $Updates) {
[string]$UpdateKey = [string]::Format('{0} [{1}|{2}]', $update.Title, $update.Date, $update.HResult);
switch ($update.Operation) {
1 {
if ($UpdateInstalled.ContainsKey($UpdateKey) -eq $FALSE) {
$UpdateInstalled.Add($UpdateKey, $update);
} else {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Warning,
[string]::Format(
'Unable to add update "{0}" to update list. The key with content "{1}" is already present',
$UpdateKey,
$update
)
);
}
};
2 {
if ($UpdateUninstalled.ContainsKey($UpdateKey) -eq $FALSE) {
$UpdateUninstalled.Add($UpdateKey, $update);
} else {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Warning,
[string]::Format(
'Unable to add update "{0}" to update list. The key with content "{1}" is already present',
$UpdateKey,
$update
)
);
}
};
default {
if ($UpdateOther.ContainsKey($UpdateKey) -eq $FALSE) {
$UpdateOther.Add($UpdateKey, $update);
} else {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Warning,
[string]::Format(
'Unable to add update "{0}" to update list. The key with content "{1}" is already present',
$UpdateKey,
$update
)
);
}
};
}
}
$UpdateList.Add('installed', $UpdateInstalled);
$UpdateList.Add('uninstalled', $UpdateUninstalled);
$UpdateList.Add('other', $UpdateOther);
return $UpdateList;

View file

@ -1,32 +0,0 @@
param($Config = $null);
function ClassMemory
{
param($Config = $null);
# This will return a hashtable with every single counter
# We specify within the array
$counter = Get-Icinga-Counter -CounterArray @(
'\Memory\Available Bytes',
'\Memory\% Committed Bytes In Use',
'\Memory\Committed Bytes',
'\Memory\Cache Bytes',
'\Memory\Pool Nonpaged Bytes',
'\Memory\Pages/sec',
'\Memory\Page Reads/sec',
'\Memory\Page Writes/sec',
'\Memory\Pages Input/sec',
'\Memory\Pages Output/sec',
'\Paging File(*)\% Usage',
'\Paging File(*)\% Usage Peak'
);
# Lets load some additional memory informations, besides current performance counters
$ComputerInformation = Get-CimInstance Win32_ComputerSystem;
$counter.Add('\Memory\Physical Memory Total Bytes', @{ 'value' = $ComputerInformation.TotalPhysicalMemory; 'sample' = @{ }; });
return $counter;
}
return ClassMemory -Config $Config;

View file

@ -1,154 +0,0 @@
param($Config = $null);
function ClassNetwork
{
param($Config = $null);
# The storage variables we require to store our data
[hashtable]$NetworkData = @{};
[hashtable]$StructuredInterfaceData = @{};
$CachedNetwork = $Icinga2.Utils.Modules.GetCacheElement(
$MyInvocation.MyCommand.Name,
'NetworkData'
);
# This will return a hashtable with every single counter
# we specify within the array. Instead of returning all
# the values in the returned hashtable, we will rebuild
# the result a little to have a improved output which
# is more user friendly and allows us to check for
# certain interfaces in detail with a simpler
# accessing possibility
$counter = Get-Icinga-Counter -CounterArray @(
'\Network Interface(*)\Bytes Received/sec',
'\Network Interface(*)\Bytes Sent/sec',
'\Network Interface(*)\Packets Received Unicast/sec',
'\Network Interface(*)\Packets Sent Unicast/sec',
'\Network Interface(*)\Packets Received Non-Unicast/sec',
'\Network Interface(*)\Packets Sent Non-Unicast/sec',
'\Network Interface(*)\Packets Outbound Errors',
'\Network Interface(*)\Packets Sent/sec',
'\Network Interface(*)\TCP RSC Exceptions/sec',
'\Network Interface(*)\Packets Outbound Discarded',
'\Network Interface(*)\TCP RSC Coalesced Packets/sec',
'\Network Interface(*)\Bytes Total/sec',
'\Network Interface(*)\Current Bandwidth',
'\Network Interface(*)\Packets Received Unknown',
'\Network Interface(*)\TCP Active RSC Connections',
'\Network Interface(*)\Offloaded Connections',
'\Network Interface(*)\Packets/sec',
'\Network Interface(*)\Packets Received Errors',
'\Network Interface(*)\Packets Received/sec',
'\Network Interface(*)\Packets Received Discarded',
'\Network Interface(*)\Output Queue Length',
'\Network Interface(*)\TCP RSC Average Packet Size'
);
# This function will help us to build a structured output based on
# interfaces found within the instances. We will use our
# Network Interface as 'index' to assign our performance Counters to.
# In addition we then provide the hashtable of counters we fetched
# above.
$StructuredInterfaceData = Get-Icinga-Counter `
-CreateStructuredOutputForCategory 'Network Interface' `
-StructuredCounterInput $counter;
$NetworkData.Add('interfaces', $StructuredInterfaceData);
# Add additional details to our interfaces, like MAC Address, Interface Index and current connection status
$NetworkAdapter = Get-WMIObject Win32_NetworkAdapter;
[hashtable]$DuplicateIDCache = @{};
foreach ($adapter in $NetworkAdapter) {
# The Performance Counter return values in brackets with [], while WMI returns ()
# In addition, WMI uses / within Interface names, while Perf Counter uses _
# We need to take care about this here
[string]$AdapterName = $adapter.Name.Replace('(', '[').Replace(')', ']');
[string]$AdapterName = $AdapterName.Replace('/', '_');
[string]$AdapterName = $AdapterName.Replace('#', '_');
# To ensure duplicate interface names will not cause this module
# to crash, we will have to build up a cache and add numeric
# additions.
if ($DuplicateIDCache.ContainsKey($AdapterName) -eq $FALSE) {
$DuplicateIDCache.Add($AdapterName, 0);
}
# In case we add adapters we have no performance counters for,
# create a new hashtable object for the name
if ($StructuredInterfaceData.ContainsKey($AdapterName) -eq $FALSE) {
$StructuredInterfaceData.Add($AdapterName, @{});
} else {
# In case the interface does already exist, check if we require
# to rename the interface with a index ID in addition. As we
# have to ensure Performance Counters are added to Physical Adapters
# only, we will focus in these indexes. All other instances will
# receive a follow-up ID.
[int]$ID = $DuplicateIDCache[$AdapterName] + 1;
if ($adapter.PhysicalAdapter -eq $FALSE) {
$ID += 1;
$DuplicateIDCache[$AdapterName] = $ID;
} else {
# Physical Adapters always have unique names, therefor we should
# always use index 1 for these to ensure Performance Counter data
# is added to the correct interfaces
$ID = 1;
}
# Only add index ID's to interfaces in case we are not equal 1
if ($ID -ne 1) {
$AdapterName = [string]::Format('{0} ({1})',
$AdapterName,
$ID
);
$StructuredInterfaceData.Add($AdapterName, @{});
}
}
# Add the WMI informations to this interface
$StructuredInterfaceData[$AdapterName].Add('NetConnectionID', $adapter.NetConnectionID);
$StructuredInterfaceData[$AdapterName].Add('InterfaceIndex', $adapter.InterfaceIndex);
$StructuredInterfaceData[$AdapterName].Add('NetConnectionStatus', $adapter.NetConnectionStatus);
$StructuredInterfaceData[$AdapterName].Add('DeviceID', $adapter.DeviceID);
$StructuredInterfaceData[$AdapterName].Add('MACAddress', $adapter.MACAddress);
$StructuredInterfaceData[$AdapterName].Add('ServiceName', $adapter.ServiceName);
$StructuredInterfaceData[$AdapterName].Add('Speed', $adapter.Speed);
$StructuredInterfaceData[$AdapterName].Add('AdapterType', $adapter.AdapterType);
$StructuredInterfaceData[$AdapterName].Add('NetworkAddresses', $adapter.NetworkAddresses);
$StructuredInterfaceData[$AdapterName].Add('Manufacturer', $adapter.Manufacturer);
$StructuredInterfaceData[$AdapterName].Add('PNPDeviceID', $adapter.PNPDeviceID);
$StructuredInterfaceData[$AdapterName].Add('PhysicalAdapter', $adapter.PhysicalAdapter);
}
# In addition to our general network interface data, it might also
# be helpful to have a look on the configured routing table
$RoutingTable = Get-CimInstance -ClassName Win32_IP4RouteTable
[array]$RoutingData = @();
foreach ($tables in $RoutingTable) {
$routes = @{};
foreach($route in $tables.CimInstanceProperties) {
$routes.Add($route.Name, $route.Value);
}
$RoutingData += $routes;
}
$NetworkData.Add('routes', $RoutingData);
$Icinga2.Utils.Modules.AddCacheElement(
$MyInvocation.MyCommand.Name,
'NetworkData',
$NetworkData
);
return $Icinga2.Utils.Modules.GetHashtableDiff(
$NetworkData.Clone(),
$CachedNetwork.Clone()
);
# At the end simply return the entire hashtable
return $NetworkData;
}
return ClassNetwork -Config $Config;

View file

@ -1,34 +0,0 @@
param($Config = $null);
function ClassNTP
{
param($Config = $null);
[hashtable]$NTPInformations = @{};
# This will return a hashtable with every single counter
# we specify within the array
$counter = Get-Icinga-Counter -CounterArray @(
'\Windows Time service\clock frequency adjustment',
'\Windows Time service\ntp client time source count',
'\Windows Time service\ntp server outgoing responses',
'\Windows Time service\computed time offset',
'\Windows Time service\ntp roundtrip delay',
'\Windows Time service\ntp server incoming requests'
);
$NTPInformations.Add('counter', $counter);
# Load the source from which we receive our NTP config
$NTPInformations.Add('source', (&W32tm /query /source));
# Load the NTP config and parse it properly
$NTPInformations.Add(
'config',
$Icinga2.Utils.IniParser.LoadFromArray(
(&W32tm /query /configuration),
$TRUE
)
);
return $NTPInformations;
}
return ClassNTP -Config $Config;

View file

@ -1,113 +0,0 @@
param($Config = $null);
$CachedProcessList = $Icinga2.Utils.Modules.GetCacheElement(
$MyInvocation.MyCommand.Name,
'ProcessList'
);
$ProcessList = Get-WmiObject Win32_Process;
$ProcessPerfList = Get-WmiObject Win32_PerfFormattedData_PerfProc_Process;
$NumberOfCPUThreads = $Icinga2.System.NumberOfCPUThreads;
[hashtable]$ProcessReference = @{};
[hashtable]$Processes = @{};
[hashtable]$ProcessValues = @{
FullList = @{ };
Removed = @( );
Added = $null;
Modified = @{ };
}
foreach ($process in $ProcessList) {
[string]$ProcessKey = [string]::Format(
'{0} [{1}]',
$process.ProcessName,
$process.ProcessId
);
[hashtable]$ProcessInfo = @{};
$ProcessInfo.Add('Name', $process.Name);
$ProcessInfo.Add('ProcessId', $process.ProcessId);
$ProcessInfo.Add('Priority', $process.Priority);
$ProcessInfo.Add('PageFileUsage', $process.PageFileUsage);
$ProcessInfo.Add('ThreadCount', $process.ThreadCount);
$ProcessInfo.Add('KernelModeTime', $process.KernelModeTime);
$ProcessInfo.Add('UserModeTime', $process.UserModeTime);
$ProcessInfo.Add('WorkingSetSize', $process.WorkingSetSize);
$ProcessInfo.Add('CommandLine', $process.CommandLine);
<#
# These are not required by now
$ProcessInfo.Add('Caption', $process.Caption);
$ProcessInfo.Add('CreationClassName', $process.CreationClassName);
$ProcessInfo.Add('CreationDate', $process.CreationDate);
$ProcessInfo.Add('CSCreationClassName', $process.CSCreationClassName);
$ProcessInfo.Add('CSName', $process.CSName);
$ProcessInfo.Add('Description', $process.Description);
$ProcessInfo.Add('ExecutablePath', $process.ExecutablePath);
$ProcessInfo.Add('ExecutionState', $process.ExecutionState);
$ProcessInfo.Add('Handle', $process.Handle);
$ProcessInfo.Add('HandleCount', $process.HandleCount);
$ProcessInfo.Add('InstallDate', $process.InstallDate);
$ProcessInfo.Add('MaximumWorkingSetSize', $process.MaximumWorkingSetSize);
$ProcessInfo.Add('MinimumWorkingSetSize', $process.MinimumWorkingSetSize);
$ProcessInfo.Add('OSCreationClassName', $process.OSCreationClassName);
$ProcessInfo.Add('OSName', $process.OSName);
$ProcessInfo.Add('OtherOperationCount', $process.OtherOperationCount);
$ProcessInfo.Add('OtherTransferCount', $process.OtherTransferCount);
$ProcessInfo.Add('PageFaults', $process.PageFaults);
$ProcessInfo.Add('ParentProcessId', $process.ParentProcessId);
$ProcessInfo.Add('PeakPageFileUsage', $process.PeakPageFileUsage);
$ProcessInfo.Add('PeakVirtualSize', $process.PeakVirtualSize);
$ProcessInfo.Add('PeakWorkingSetSize', $process.PeakWorkingSetSize);
$ProcessInfo.Add('PrivatePageCount', $process.PrivatePageCount);
$ProcessInfo.Add('QuotaNonPagedPoolUsage', $process.QuotaNonPagedPoolUsage);
$ProcessInfo.Add('QuotaPagedPoolUsage', $process.QuotaPagedPoolUsage);
$ProcessInfo.Add('QuotaPeakNonPagedPoolUsage', $process.QuotaPeakNonPagedPoolUsage);
$ProcessInfo.Add('QuotaPeakPagedPoolUsage', $process.QuotaPeakPagedPoolUsage);
$ProcessInfo.Add('ReadOperationCount', $process.ReadOperationCount);
$ProcessInfo.Add('ReadTransferCount', $process.ReadTransferCount);
$ProcessInfo.Add('SessionId', $process.SessionId);
$ProcessInfo.Add('Status', $process.Status);
$ProcessInfo.Add('TerminationDate', $process.TerminationDate);
$ProcessInfo.Add('VirtualSize', $process.VirtualSize);
$ProcessInfo.Add('WindowsVersion', $process.WindowsVersion);
$ProcessInfo.Add('WriteOperationCount', $process.WriteOperationCount);
$ProcessInfo.Add('WriteTransferCount', $process.WriteTransferCount);
#>
$ProcessReference.Add($process.ProcessId, $ProcessKey);
$Processes.Add($ProcessKey, $ProcessInfo);
}
foreach ($perfdata in $ProcessPerfList) {
if ($perfdata.Name -eq '_Total') {
continue;
}
if ($ProcessReference.ContainsKey($perfdata.IDProcess)) {
$Processes[$ProcessReference[$perfdata.IDProcess]].Add(
'WorkingSetPrivate',
$perfdata.WorkingSetPrivate
);
# Note: In order to get the correct CPU time in % we have to divide the
# Processor Time with the amount of threads installed on our CPU
$Processes[$ProcessReference[$perfdata.IDProcess]].Add(
'PercentProcessorTime',
[math]::Round(($perfdata.PercentProcessorTime / $NumberOfCPUThreads), 2)
);
}
}
$Processes.Add('count', $Processes.count);
$Icinga2.Utils.Modules.AddCacheElement(
$MyInvocation.MyCommand.Name,
'ProcessList',
$Processes
);
return $Icinga2.Utils.Modules.GetHashtableDiff(
$Processes.Clone(),
$CachedProcessList.Clone(),
@('ProcessId')
);

View file

@ -1,62 +0,0 @@
param($Config = $null);
function ClassService()
{
param($Config = $null);
$services = Get-Service;
[hashtable]$ServiceData = @{};
$CachedServiceData = $Icinga2.Utils.Modules.GetCacheElement(
$MyInvocation.MyCommand.Name,
'ServiceData'
);
foreach ($service in $services) {
[hashtable]$ServiceInfo = @{};
$ServiceInfo.Add('display_name', $service.DisplayName);
$ServiceInfo.Add('service_name', $service.ServiceName);
$ServiceInfo.Add('can_pause_and_continue', $service.CanPauseAndContinue);
$ServiceInfo.Add('can_shutdown', $service.CanShutdown);
$ServiceInfo.Add('can_stop', $service.CanStop);
$ServiceInfo.Add('service_handle', $service.ServiceHandle);
$ServiceInfo.Add('status', $service.Status);
$ServiceInfo.Add('service_type', $service.ServiceType);
$ServiceInfo.Add('start_type', $service.StartType);
$ServiceInfo.Add('site', $service.Site);
$ServiceInfo.Add('container', $service.Container);
[array]$DependentServices = $null;
foreach ($dependency in $service.DependentServices) {
if ($DependentServices -eq $null) { $DependentServices = @(); }
$DependentServices += $dependency.Name;
}
$ServiceInfo.Add('dependent_services', $DependentServices);
[array]$DependentServices = $null;
foreach ($dependency in $service.ServicesDependedOn) {
if ($DependentServices -eq $null) { $DependentServices = @(); }
$DependentServices += $dependency.Name;
}
$ServiceInfo.Add('depends_on', $DependentServices);
$ServiceData.Add($service.Name, $ServiceInfo);
}
$Icinga2.Utils.Modules.AddCacheElement(
$MyInvocation.MyCommand.Name,
'ServiceData',
$ServiceData
);
return $Icinga2.Utils.Modules.GetHashtableDiff(
$ServiceData.Clone(),
$CachedServiceData.Clone(),
@('service_name')
);
return $ServiceData;
}
return ClassService -Config $Config;

View file

@ -1,6 +0,0 @@
param($Config = $null);
return $Icinga2.Utils.Modules.LoadIncludes(
$MyInvocation.MyCommand.Name,
$Config
);

View file

@ -1,16 +0,0 @@
param($Config = $null);
function ClassWindows
{
param($Config = $null);
$WindowsInformations = Get-CimInstance Win32_OperatingSystem;
$windows_datails = @{};
foreach($cpu_core in $WindowsInformations.CimInstanceProperties) {
$windows_datails.Add($cpu_core.Name, $cpu_core.Value);
}
return $windows_datails;
}
return ClassWindows -Config $Config;