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.
This commit is contained in:
Lord Hepipud 2022-06-03 14:17:24 +02:00 committed by GitHub
commit 1b2e3a6ee1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 112 additions and 2 deletions

View file

@ -19,6 +19,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
* [#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
* [#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.
* [#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
## 1.9.1 (2022-05-13)

View file

@ -0,0 +1,46 @@
function Read-IcingaStateFile()
{
param (
[switch]$WriteOutput = $FALSE
);
[string]$StateFilePath = Join-Path -Path $ENV:ProgramData -ChildPath 'icinga2\var\lib\icinga2\icinga2.state';
if ((Test-Path $StateFilePath) -eq $FALSE) {
return $TRUE;
}
$StateFileContent = Get-Content -Path $StateFilePath -Encoding 'UTF8' -Raw;
$FileInformation = Get-Item -Path $StateFilePath;
if ([string]::IsNullOrEmpty($StateFileContent)) {
return $FALSE;
}
while ($TRUE) {
try {
if ([string]::IsNullOrEmpty($StateFileContent)) {
break;
}
if ($StateFileContent.Contains(':') -eq $FALSE) {
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);
return $FALSE;
}
[int]$IndexOfJSON = $StateFileContent.IndexOf(':');
[int]$StatementSize = $StateFileContent.SubString(0, $IndexOfJSON);
[string]$JSONString = $StateFileContent.Substring($IndexOfJSON + 1, $StatementSize);
[int]$TotalMsgLen = $IndexOfJSON + $StatementSize + 2;
$StateFileContent = $StateFileContent.Substring($TotalMsgLen, $StateFileContent.Length - $TotalMsgLen);
$JsonValid = ConvertFrom-Json -InputObject $JSONString -ErrorAction Stop;
} catch {
[string]$ErrMessage = [string]::Format('The Icinga Agent state file validation failed with an exception: "{0}"', $_.Exception.Message);
Write-IcingaTestOutput -Severity 'Failed' -Message $ErrMessage -DropMessage:(-Not $WriteOutput);
return $FALSE;
}
}
return $TRUE;
}

View file

@ -0,0 +1,21 @@
function Repair-IcingaStateFile()
{
param (
[switch]$Force
);
[string]$StateFilePath = Join-Path -Path $ENV:ProgramData -ChildPath 'icinga2\var\lib\icinga2\icinga2.state*';
if ((Test-IcingaStateFile) -And $Force -eq $FALSE) {
Write-IcingaConsoleNotice -Message 'The Icinga Agent state file seems to be okay';
return;
}
$Success = Remove-ItemSecure -Path $StateFilePath -Force -Retries 5;
if ($Success) {
Write-IcingaConsoleNotice -Message 'The corrupted Icinga Agent State files have been removed';
} else {
Write-IcingaConsoleError -Message 'Failed to remove the corrupted Icinga Agent state files';
}
}

View file

@ -18,6 +18,7 @@ function Test-IcingaAgent()
Test-IcingaAcl (Get-IcingaCacheDir) -WriteOutput | Out-Null;
Test-IcingaAcl (Get-IcingaPowerShellConfigDir) -WriteOutput | Out-Null;
Test-IcingaAcl -Directory (Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'certificate') -WriteOutput | Out-Null;
Test-IcingaStateFile -WriteOutput | Out-Null;
if ($IcingaAgentData.Installed) {
Test-IcingaAgentConfig | Out-Null;

View file

@ -0,0 +1,25 @@
function Test-IcingaStateFile()
{
param (
[switch]$WriteOutput = $FALSE
);
$IcingaAgentData = Get-IcingaAgentInstallation;
[string]$StateFilePath = Join-Path -Path $ENV:ProgramData -ChildPath 'icinga2\var\lib\icinga2\icinga2.state';
if ((Test-Path $StateFilePath) -eq $FALSE) {
Write-IcingaTestOutput -Severity 'Passed' -Message 'The Icinga Agent state file does not exist' -DropMessage:(-Not $WriteOutput);
return $TRUE;
}
$Success = Read-IcingaStateFile;
if ($Success) {
Write-IcingaTestOutput -Severity 'Passed' -Message 'The Icinga Agent state file is healthy' -DropMessage:(-Not $WriteOutput);
return $TRUE;
} else {
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);
}
return $FALSE;
}

View file

@ -3,9 +3,14 @@ function Write-IcingaTestOutput()
param(
[ValidateSet('Passed', 'Warning', 'Failed')]
$Severity,
$Message
$Message,
[switch]$DropMessage = $FALSE
);
if ($DropMessage) {
return;
}
$Color = 'Green';
Switch ($Severity) {

View file

@ -43,7 +43,7 @@ function Show-IcingaForWindowsMenuManageTroubleshooting()
},
@{
'Caption' = 'Repair Icinga Agent service';
'Command' = 'Show-IcingaForWindowsMenuManageIcingaForWindowsServices';
'Command' = 'Show-IcingaForWindowsMenuManageTroubleshooting';
'Help' = 'Allows to repair the Icinga Agent service in case it was removed or broke during installation/upgrade';
'Disabled' = ($null -ne $IcingaAgentService);
'DisabledReason' = 'The Icinga Agent service is already present';
@ -52,6 +52,17 @@ function Show-IcingaForWindowsMenuManageTroubleshooting()
'Command' = 'Repair-IcingaService';
}
},
@{
'Caption' = 'Repair Icinga Agent state file';
'Command' = 'Show-IcingaForWindowsMenuManageTroubleshooting';
'Help' = 'Allows to repair the Icinga Agent state file, in case the file is corrupt';
'Disabled' = (Test-IcingaStateFile);
'DisabledReason' = 'The Icinga Agent state file is healthy';
'AdminMenu' = $TRUE;
'Action' = @{
'Command' = 'Repair-IcingaStateFile';
}
},
@{
'Caption' = 'Allow untrusted certificate communication (This session)';
'Command' = 'Show-IcingaForWindowsMenuManageTroubleshooting';