mirror of
https://github.com/Icinga/icinga-powershell-framework.git
synced 2025-12-20 23:00:35 -05:00
161 lines
5 KiB
PowerShell
161 lines
5 KiB
PowerShell
|
|
$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;
|