Skip to content

Commit 1b2e3a6

Browse files
authored
Merge pull request #531 from Icinga:feature/icinga_state_file_test_and_repair
Feature: Adds test and repair for the Icinga Agent state file Adds new Cmdlets to test and repair the Icinga Agent state file, in case the file is corrupt. The `Test-IcingaAgent` will now check by default of the state is present and in case it is, if the file is healthy or corrupted. A repair command `Repair-IcingaStateFile` will remove the corrupted files afterwards to ensure the Icinga Agent can be started as service again.
2 parents 6b0e177 + 55be30f commit 1b2e3a6

File tree

8 files changed

+112
-2
lines changed

8 files changed

+112
-2
lines changed

doc/100-General/10-Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
1919

2020
* [#40](https://github.com/Icinga/icinga-powershell-framework/issues/40) Adds support to set service recovery for the Icinga Agent and Icinga for Windows service, to restart them in case of a crash or error
2121
* [#525](https://github.com/Icinga/icinga-powershell-framework/pull/525) Adds new developer mode for `icinga` command and improved cache handling, to ensure within `-DeveloperMode` and inside a VS Code environment, the framework cache file is never overwritten, while still all functions are loaded and imported.
22+
* [#531](https://github.com/Icinga/icinga-powershell-framework/pull/531) Adds `Test-IcingaStateFile` and `Repair-IcingaStateFile`, which is integrated into `Test-IcingaAgent`, to ensure the Icinga Agent state file is healthy and not corrupt, causing the Icinga Agent to fail on start
2223

2324
## 1.9.1 (2022-05-13)
2425

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
function Read-IcingaStateFile()
2+
{
3+
param (
4+
[switch]$WriteOutput = $FALSE
5+
);
6+
7+
[string]$StateFilePath = Join-Path -Path $ENV:ProgramData -ChildPath 'icinga2\var\lib\icinga2\icinga2.state';
8+
9+
if ((Test-Path $StateFilePath) -eq $FALSE) {
10+
return $TRUE;
11+
}
12+
13+
$StateFileContent = Get-Content -Path $StateFilePath -Encoding 'UTF8' -Raw;
14+
$FileInformation = Get-Item -Path $StateFilePath;
15+
16+
if ([string]::IsNullOrEmpty($StateFileContent)) {
17+
return $FALSE;
18+
}
19+
20+
while ($TRUE) {
21+
try {
22+
if ([string]::IsNullOrEmpty($StateFileContent)) {
23+
break;
24+
}
25+
26+
if ($StateFileContent.Contains(':') -eq $FALSE) {
27+
Write-IcingaTestOutput -Severity 'Failed' -Message 'The start index of the Icinga Agent state file could not be found. The file seems to be corrupt.' -DropMessage:(-Not $WriteOutput);
28+
return $FALSE;
29+
}
30+
31+
[int]$IndexOfJSON = $StateFileContent.IndexOf(':');
32+
[int]$StatementSize = $StateFileContent.SubString(0, $IndexOfJSON);
33+
[string]$JSONString = $StateFileContent.Substring($IndexOfJSON + 1, $StatementSize);
34+
[int]$TotalMsgLen = $IndexOfJSON + $StatementSize + 2;
35+
$StateFileContent = $StateFileContent.Substring($TotalMsgLen, $StateFileContent.Length - $TotalMsgLen);
36+
$JsonValid = ConvertFrom-Json -InputObject $JSONString -ErrorAction Stop;
37+
} catch {
38+
[string]$ErrMessage = [string]::Format('The Icinga Agent state file validation failed with an exception: "{0}"', $_.Exception.Message);
39+
Write-IcingaTestOutput -Severity 'Failed' -Message $ErrMessage -DropMessage:(-Not $WriteOutput);
40+
41+
return $FALSE;
42+
}
43+
}
44+
45+
return $TRUE;
46+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
function Repair-IcingaStateFile()
2+
{
3+
param (
4+
[switch]$Force
5+
);
6+
7+
[string]$StateFilePath = Join-Path -Path $ENV:ProgramData -ChildPath 'icinga2\var\lib\icinga2\icinga2.state*';
8+
9+
if ((Test-IcingaStateFile) -And $Force -eq $FALSE) {
10+
Write-IcingaConsoleNotice -Message 'The Icinga Agent state file seems to be okay';
11+
return;
12+
}
13+
14+
$Success = Remove-ItemSecure -Path $StateFilePath -Force -Retries 5;
15+
16+
if ($Success) {
17+
Write-IcingaConsoleNotice -Message 'The corrupted Icinga Agent State files have been removed';
18+
} else {
19+
Write-IcingaConsoleError -Message 'Failed to remove the corrupted Icinga Agent state files';
20+
}
21+
}

lib/core/icingaagent/tests/Test-IcingaAgent.psm1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ function Test-IcingaAgent()
1818
Test-IcingaAcl (Get-IcingaCacheDir) -WriteOutput | Out-Null;
1919
Test-IcingaAcl (Get-IcingaPowerShellConfigDir) -WriteOutput | Out-Null;
2020
Test-IcingaAcl -Directory (Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'certificate') -WriteOutput | Out-Null;
21+
Test-IcingaStateFile -WriteOutput | Out-Null;
2122

2223
if ($IcingaAgentData.Installed) {
2324
Test-IcingaAgentConfig | Out-Null;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
function Test-IcingaStateFile()
2+
{
3+
param (
4+
[switch]$WriteOutput = $FALSE
5+
);
6+
7+
$IcingaAgentData = Get-IcingaAgentInstallation;
8+
[string]$StateFilePath = Join-Path -Path $ENV:ProgramData -ChildPath 'icinga2\var\lib\icinga2\icinga2.state';
9+
10+
if ((Test-Path $StateFilePath) -eq $FALSE) {
11+
Write-IcingaTestOutput -Severity 'Passed' -Message 'The Icinga Agent state file does not exist' -DropMessage:(-Not $WriteOutput);
12+
return $TRUE;
13+
}
14+
15+
$Success = Read-IcingaStateFile;
16+
17+
if ($Success) {
18+
Write-IcingaTestOutput -Severity 'Passed' -Message 'The Icinga Agent state file is healthy' -DropMessage:(-Not $WriteOutput);
19+
return $TRUE;
20+
} else {
21+
Write-IcingaTestOutput -Severity 'Failed' -Message 'The Icinga Agent state file is corrupt. Use the "Repair-IcingaStateFile" command to repair the file or "Read-IcingaStateFile -WriteOutput" for further details' -DropMessage:(-Not $WriteOutput);
22+
}
23+
24+
return $FALSE;
25+
}

lib/core/icingaagent/writers/Write-IcingaTestOutput.psm1

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@ function Write-IcingaTestOutput()
33
param(
44
[ValidateSet('Passed', 'Warning', 'Failed')]
55
$Severity,
6-
$Message
6+
$Message,
7+
[switch]$DropMessage = $FALSE
78
);
89

10+
if ($DropMessage) {
11+
return;
12+
}
13+
914
$Color = 'Green';
1015

1116
Switch ($Severity) {

lib/core/installer/menu/manage/settings/troubleshooting/Troubleshooting.psm1

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ function Show-IcingaForWindowsMenuManageTroubleshooting()
4343
},
4444
@{
4545
'Caption' = 'Repair Icinga Agent service';
46-
'Command' = 'Show-IcingaForWindowsMenuManageIcingaForWindowsServices';
46+
'Command' = 'Show-IcingaForWindowsMenuManageTroubleshooting';
4747
'Help' = 'Allows to repair the Icinga Agent service in case it was removed or broke during installation/upgrade';
4848
'Disabled' = ($null -ne $IcingaAgentService);
4949
'DisabledReason' = 'The Icinga Agent service is already present';
@@ -52,6 +52,17 @@ function Show-IcingaForWindowsMenuManageTroubleshooting()
5252
'Command' = 'Repair-IcingaService';
5353
}
5454
},
55+
@{
56+
'Caption' = 'Repair Icinga Agent state file';
57+
'Command' = 'Show-IcingaForWindowsMenuManageTroubleshooting';
58+
'Help' = 'Allows to repair the Icinga Agent state file, in case the file is corrupt';
59+
'Disabled' = (Test-IcingaStateFile);
60+
'DisabledReason' = 'The Icinga Agent state file is healthy';
61+
'AdminMenu' = $TRUE;
62+
'Action' = @{
63+
'Command' = 'Repair-IcingaStateFile';
64+
}
65+
},
5566
@{
5667
'Caption' = 'Allow untrusted certificate communication (This session)';
5768
'Command' = 'Show-IcingaForWindowsMenuManageTroubleshooting';

0 commit comments

Comments
 (0)