Added new functionality: checking HIP hosts for TCP connectivity and whether they can be reached via RDP.
This commit is contained in:
@@ -41,6 +41,7 @@ namespace BizTalkMonitorConfigGenerator.Configuration
|
||||
config.GeneratedMonitorConfig.Logging = config.GeneratedMonitorConfig.Logging ?? new LoggingOptions();
|
||||
config.GeneratedMonitorConfig.EventLog = config.GeneratedMonitorConfig.EventLog ?? new EventLogOptions();
|
||||
config.GeneratedMonitorConfig.Email = config.GeneratedMonitorConfig.Email ?? new EmailOptions();
|
||||
config.GeneratedMonitorConfig.HipVirtualMachines = config.GeneratedMonitorConfig.HipVirtualMachines ?? new HipVirtualMachineOptions();
|
||||
config.GeneratedMonitorConfig.Email.To = RecipientListHelper.SanitizeRecipientList(config.GeneratedMonitorConfig.Email.To);
|
||||
config.GeneratedMonitorConfig.Email.Cc = RecipientListHelper.SanitizeRecipientList(config.GeneratedMonitorConfig.Email.Cc);
|
||||
config.GeneratedMonitorConfig.Email.Bcc = RecipientListHelper.SanitizeRecipientList(config.GeneratedMonitorConfig.Email.Bcc);
|
||||
@@ -213,6 +214,7 @@ namespace BizTalkMonitorConfigGenerator.Configuration
|
||||
configuration.Logging = configuration.Logging ?? new LoggingOptions();
|
||||
configuration.EventLog = configuration.EventLog ?? new EventLogOptions();
|
||||
configuration.Email = configuration.Email ?? new EmailOptions();
|
||||
configuration.HipVirtualMachines = configuration.HipVirtualMachines ?? new HipVirtualMachineOptions();
|
||||
configuration.Targets = configuration.Targets ?? new List<TargetOptions>();
|
||||
|
||||
if (configuration.Runtime.MaxConcurrency <= 0)
|
||||
@@ -225,6 +227,24 @@ namespace BizTalkMonitorConfigGenerator.Configuration
|
||||
throw new InvalidOperationException("GeneratedMonitorConfig.Logging.RetentionDays darf nicht negativ sein.");
|
||||
}
|
||||
|
||||
if (configuration.HipVirtualMachines.Enabled)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(configuration.HipVirtualMachines.ConfigPath))
|
||||
{
|
||||
throw new InvalidOperationException("GeneratedMonitorConfig.HipVirtualMachines.Enabled=true, aber ConfigPath ist leer.");
|
||||
}
|
||||
|
||||
if (configuration.HipVirtualMachines.TimeoutSeconds <= 0)
|
||||
{
|
||||
configuration.HipVirtualMachines.TimeoutSeconds = 5;
|
||||
}
|
||||
|
||||
if (configuration.HipVirtualMachines.RdpPort <= 0 || configuration.HipVirtualMachines.RdpPort > 65535)
|
||||
{
|
||||
throw new InvalidOperationException("GeneratedMonitorConfig.HipVirtualMachines.RdpPort muss zwischen 1 und 65535 liegen.");
|
||||
}
|
||||
}
|
||||
|
||||
if (configuration.Email.Enabled)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(configuration.Email.SmtpHost))
|
||||
@@ -306,6 +326,16 @@ namespace BizTalkMonitorConfigGenerator.Configuration
|
||||
CooldownMinutes = configuration.Email.CooldownMinutes,
|
||||
TimeoutSeconds = configuration.Email.TimeoutSeconds
|
||||
},
|
||||
HipVirtualMachines = new HipVirtualMachineOptions
|
||||
{
|
||||
Enabled = configuration.HipVirtualMachines.Enabled,
|
||||
ConfigPath = configuration.HipVirtualMachines.ConfigPath,
|
||||
ApplicationName = configuration.HipVirtualMachines.ApplicationName,
|
||||
TimeoutSeconds = configuration.HipVirtualMachines.TimeoutSeconds,
|
||||
RdpPort = configuration.HipVirtualMachines.RdpPort,
|
||||
CheckNetwork = configuration.HipVirtualMachines.CheckNetwork,
|
||||
CheckRdp = configuration.HipVirtualMachines.CheckRdp
|
||||
},
|
||||
Targets = new List<TargetOptions>()
|
||||
};
|
||||
|
||||
|
||||
@@ -94,6 +94,15 @@
|
||||
"CooldownMinutes": 0,
|
||||
"TimeoutSeconds": 30
|
||||
},
|
||||
"HipVirtualMachines": {
|
||||
"Enabled": true,
|
||||
"ConfigPath": "hip-vms.json",
|
||||
"ApplicationName": "HIP Virtual Machines",
|
||||
"TimeoutSeconds": 5,
|
||||
"RdpPort": 3389,
|
||||
"CheckNetwork": true,
|
||||
"CheckRdp": true
|
||||
},
|
||||
"Targets": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Web.Script.Serialization;
|
||||
|
||||
namespace HostAvailabilityMonitor.Configuration
|
||||
{
|
||||
public sealed class HipVirtualMachineConfiguration
|
||||
{
|
||||
public List<HipVirtualMachine> VirtualMachines { get; set; } = new List<HipVirtualMachine>();
|
||||
|
||||
public static HipVirtualMachineConfiguration Load(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
throw new ArgumentException("Der Pfad zur HIP-VM-Konfiguration ist leer.", nameof(path));
|
||||
}
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
throw new FileNotFoundException("HIP-VM-Konfiguration wurde nicht gefunden: " + path, path);
|
||||
}
|
||||
|
||||
var json = File.ReadAllText(path);
|
||||
var serializer = new JavaScriptSerializer();
|
||||
var config = serializer.Deserialize<HipVirtualMachineConfiguration>(json);
|
||||
if (config == null)
|
||||
{
|
||||
throw new InvalidOperationException("HIP-VM-Konfiguration konnte nicht deserialisiert werden.");
|
||||
}
|
||||
|
||||
config.VirtualMachines = config.VirtualMachines ?? new List<HipVirtualMachine>();
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class HipVirtualMachine
|
||||
{
|
||||
public string Group { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Address { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public bool Enabled { get; set; } = true;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ namespace HostAvailabilityMonitor.Configuration
|
||||
public LoggingOptions Logging { get; set; } = new LoggingOptions();
|
||||
public EventLogOptions EventLog { get; set; } = new EventLogOptions();
|
||||
public EmailOptions Email { get; set; } = new EmailOptions();
|
||||
public HipVirtualMachineOptions HipVirtualMachines { get; set; } = new HipVirtualMachineOptions();
|
||||
public List<TargetOptions> Targets { get; set; } = new List<TargetOptions>();
|
||||
|
||||
public static MonitorConfiguration Load(string path)
|
||||
@@ -36,6 +37,7 @@ namespace HostAvailabilityMonitor.Configuration
|
||||
config.Logging = config.Logging ?? new LoggingOptions();
|
||||
config.EventLog = config.EventLog ?? new EventLogOptions();
|
||||
config.Email = config.Email ?? new EmailOptions();
|
||||
config.HipVirtualMachines = config.HipVirtualMachines ?? new HipVirtualMachineOptions();
|
||||
config.Email.To = SanitizeRecipientList(config.Email.To);
|
||||
config.Email.Cc = SanitizeRecipientList(config.Email.Cc);
|
||||
config.Email.Bcc = SanitizeRecipientList(config.Email.Bcc);
|
||||
@@ -84,7 +86,9 @@ namespace HostAvailabilityMonitor.Configuration
|
||||
|
||||
public void Validate()
|
||||
{
|
||||
if (Targets == null || Targets.Count == 0)
|
||||
Targets = Targets ?? new List<TargetOptions>();
|
||||
|
||||
if ((Targets == null || Targets.Count == 0) && (HipVirtualMachines == null || !HipVirtualMachines.Enabled))
|
||||
{
|
||||
throw new InvalidOperationException("Es wurde kein Ziel in der Konfiguration definiert.");
|
||||
}
|
||||
@@ -112,6 +116,29 @@ namespace HostAvailabilityMonitor.Configuration
|
||||
Runtime.MaxConcurrency = 1;
|
||||
}
|
||||
|
||||
if (HipVirtualMachines == null)
|
||||
{
|
||||
HipVirtualMachines = new HipVirtualMachineOptions();
|
||||
}
|
||||
|
||||
if (HipVirtualMachines.Enabled)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(HipVirtualMachines.ConfigPath))
|
||||
{
|
||||
throw new InvalidOperationException("HipVirtualMachines.Enabled=true, aber ConfigPath ist leer.");
|
||||
}
|
||||
|
||||
if (HipVirtualMachines.TimeoutSeconds <= 0)
|
||||
{
|
||||
HipVirtualMachines.TimeoutSeconds = 5;
|
||||
}
|
||||
|
||||
if (HipVirtualMachines.RdpPort <= 0 || HipVirtualMachines.RdpPort > 65535)
|
||||
{
|
||||
throw new InvalidOperationException("HipVirtualMachines.RdpPort muss zwischen 1 und 65535 liegen.");
|
||||
}
|
||||
}
|
||||
|
||||
if (Logging.RetentionDays < 0)
|
||||
{
|
||||
throw new InvalidOperationException("Logging.RetentionDays darf nicht negativ sein.");
|
||||
@@ -227,6 +254,17 @@ namespace HostAvailabilityMonitor.Configuration
|
||||
public int TimeoutSeconds { get; set; } = 30;
|
||||
}
|
||||
|
||||
public sealed class HipVirtualMachineOptions
|
||||
{
|
||||
public bool Enabled { get; set; } = false;
|
||||
public string ConfigPath { get; set; } = "hip-vms.json";
|
||||
public string ApplicationName { get; set; } = "HIP Virtual Machines";
|
||||
public int TimeoutSeconds { get; set; } = 5;
|
||||
public int RdpPort { get; set; } = 3389;
|
||||
public bool CheckNetwork { get; set; } = true;
|
||||
public bool CheckRdp { get; set; } = true;
|
||||
}
|
||||
|
||||
public sealed class TargetOptions
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
@@ -236,6 +274,11 @@ namespace HostAvailabilityMonitor.Configuration
|
||||
public int? Port { get; set; }
|
||||
public bool? ValidateUncPathAccess { get; set; }
|
||||
public string HttpMethod { get; set; }
|
||||
public string Source { get; set; }
|
||||
public string Group { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string MachineName { get; set; }
|
||||
public string CheckName { get; set; }
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
public string DisplayName
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Configuration\HipVirtualMachineConfiguration.cs" />
|
||||
<Compile Include="Configuration\MonitorConfiguration.cs" />
|
||||
<Compile Include="Logging\FileLogger.cs" />
|
||||
<Compile Include="Logging\WindowsEventLogger.cs" />
|
||||
@@ -56,6 +57,9 @@
|
||||
<Content Include="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="hip-vms.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
|
||||
@@ -104,6 +104,26 @@ namespace HostAvailabilityMonitor.Logging
|
||||
parts.Add("Port=" + result.Port.Value);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(result.Source))
|
||||
{
|
||||
parts.Add("Source=" + Escape(result.Source));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(result.Group))
|
||||
{
|
||||
parts.Add("Group=" + Escape(result.Group));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(result.MachineName))
|
||||
{
|
||||
parts.Add("Machine=" + Escape(result.MachineName));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(result.CheckName))
|
||||
{
|
||||
parts.Add("Check=" + Escape(result.CheckName));
|
||||
}
|
||||
|
||||
if (result.HttpStatusCode.HasValue)
|
||||
{
|
||||
parts.Add("HttpStatus=" + result.HttpStatusCode.Value);
|
||||
|
||||
@@ -65,12 +65,14 @@ namespace HostAvailabilityMonitor.Monitoring
|
||||
return await CheckTcpAsync(target, uri.Host, target.Port ?? ResolvePort(uri, null), startedAt, TargetKind.Tcp, endpoint, cancellationToken).ConfigureAwait(false);
|
||||
case "icmp":
|
||||
return await CheckIcmpAsync(target, uri.Host, startedAt, endpoint, cancellationToken).ConfigureAwait(false);
|
||||
case "rdp":
|
||||
return await CheckTcpAsync(target, uri.Host, target.Port ?? ResolvePort(uri, 3389), startedAt, TargetKind.Rdp, endpoint, cancellationToken).ConfigureAwait(false);
|
||||
case "ftp":
|
||||
return await CheckTcpAsync(target, uri.Host, target.Port ?? ResolvePort(uri, 21), startedAt, TargetKind.Ftp, endpoint, cancellationToken).ConfigureAwait(false);
|
||||
case "file":
|
||||
return await CheckFileUriAsync(target, uri, startedAt, cancellationToken).ConfigureAwait(false);
|
||||
default:
|
||||
return Fail(target, TargetKind.Unknown, endpoint, startedAt, "Nicht unterstütztes Schema '" + uri.Scheme + "'. Unterstützt: UNC, file, http, https, sftp, ftp, tcp, icmp.", null, uri.Host, uri.IsDefaultPort ? (int?)null : uri.Port);
|
||||
return Fail(target, TargetKind.Unknown, endpoint, startedAt, "Nicht unterstütztes Schema '" + uri.Scheme + "'. Unterstützt: UNC, file, http, https, sftp, ftp, tcp, icmp, rdp.", null, uri.Host, uri.IsDefaultPort ? (int?)null : uri.Port);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,6 +397,11 @@ namespace HostAvailabilityMonitor.Monitoring
|
||||
Detail = detail,
|
||||
Host = host,
|
||||
Port = port,
|
||||
Source = target.Source,
|
||||
Group = target.Group,
|
||||
Description = target.Description,
|
||||
MachineName = target.MachineName,
|
||||
CheckName = target.CheckName,
|
||||
HttpStatusCode = httpStatusCode,
|
||||
ErrorType = errorType,
|
||||
StartedAtLocal = startedAt,
|
||||
|
||||
@@ -13,7 +13,8 @@ namespace HostAvailabilityMonitor.Monitoring
|
||||
Icmp = 6,
|
||||
Host = 7,
|
||||
Ftp = 8,
|
||||
File = 9
|
||||
File = 9,
|
||||
Rdp = 10
|
||||
}
|
||||
|
||||
public sealed class ProbeResult
|
||||
@@ -29,6 +30,11 @@ namespace HostAvailabilityMonitor.Monitoring
|
||||
public string Detail { get; set; }
|
||||
public string Host { get; set; }
|
||||
public int? Port { get; set; }
|
||||
public string Source { get; set; }
|
||||
public string Group { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string MachineName { get; set; }
|
||||
public string CheckName { get; set; }
|
||||
public int? HttpStatusCode { get; set; }
|
||||
public string ErrorType { get; set; }
|
||||
public DateTimeOffset StartedAtLocal { get; set; }
|
||||
|
||||
@@ -276,6 +276,8 @@ namespace HostAvailabilityMonitor.Notifications
|
||||
sb.AppendLine("Aktuell sind keine Endpunkte down / There are currently no unavailable endpoints.");
|
||||
}
|
||||
|
||||
AppendHipVirtualMachineSnapshot(sb, summary.CurrentResults);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
@@ -296,6 +298,22 @@ namespace HostAvailabilityMonitor.Notifications
|
||||
{
|
||||
sb.AppendLine(" Port: " + result.Port.Value);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(result.Group))
|
||||
{
|
||||
sb.AppendLine(" Gruppe / Group: " + result.Group);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(result.MachineName))
|
||||
{
|
||||
sb.AppendLine(" Maschine / Machine: " + result.MachineName);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(result.CheckName))
|
||||
{
|
||||
sb.AppendLine(" Check: " + result.CheckName);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(result.Description))
|
||||
{
|
||||
sb.AppendLine(" Beschreibung / Description: " + result.Description);
|
||||
}
|
||||
if (result.HttpStatusCode.HasValue)
|
||||
{
|
||||
sb.AppendLine(" HTTP Status: " + result.HttpStatusCode.Value);
|
||||
@@ -310,6 +328,84 @@ namespace HostAvailabilityMonitor.Notifications
|
||||
}
|
||||
}
|
||||
|
||||
private static void AppendHipVirtualMachineSnapshot(StringBuilder sb, IReadOnlyCollection<ProbeResult> results)
|
||||
{
|
||||
if (results == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var vmResults = results
|
||||
.Where(r => r != null && string.Equals(r.Source, "HipVirtualMachines", StringComparison.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
if (vmResults.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("HIP-VM Snapshot / HIP VM snapshot:");
|
||||
|
||||
var networkUp = vmResults.Count(r => string.Equals(r.CheckName, "Network", StringComparison.OrdinalIgnoreCase) && r.IsSuccess);
|
||||
var networkDown = vmResults.Count(r => string.Equals(r.CheckName, "Network", StringComparison.OrdinalIgnoreCase) && !r.IsSkipped && !r.IsSuccess);
|
||||
var rdpUp = vmResults.Count(r => string.Equals(r.CheckName, "RDP", StringComparison.OrdinalIgnoreCase) && r.IsSuccess);
|
||||
var rdpDown = vmResults.Count(r => string.Equals(r.CheckName, "RDP", StringComparison.OrdinalIgnoreCase) && !r.IsSkipped && !r.IsSuccess);
|
||||
sb.AppendLine("- Netzwerk / Network UP: " + networkUp + ", DOWN: " + networkDown);
|
||||
sb.AppendLine("- RDP UP: " + rdpUp + ", DOWN: " + rdpDown);
|
||||
|
||||
var groups = vmResults
|
||||
.GroupBy(r => BuildVmSnapshotKey(r), StringComparer.OrdinalIgnoreCase)
|
||||
.OrderBy(g => FirstNonEmpty(g.Select(r => r.Group)), StringComparer.OrdinalIgnoreCase)
|
||||
.ThenBy(g => FirstNonEmpty(g.Select(r => r.MachineName)), StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var group in groups)
|
||||
{
|
||||
var entries = group.ToList();
|
||||
var first = entries[0];
|
||||
var network = entries.FirstOrDefault(r => string.Equals(r.CheckName, "Network", StringComparison.OrdinalIgnoreCase));
|
||||
var rdp = entries.FirstOrDefault(r => string.Equals(r.CheckName, "RDP", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
sb.AppendLine("- " + Safe(first.Group) + " | " + Safe(first.MachineName) + " | " + Safe(first.Description));
|
||||
sb.AppendLine(" Netzwerk / Network: " + FormatCompactStatus(network));
|
||||
sb.AppendLine(" RDP: " + FormatCompactStatus(rdp));
|
||||
}
|
||||
}
|
||||
|
||||
private static string BuildVmSnapshotKey(ProbeResult result)
|
||||
{
|
||||
return string.Join("|", new[]
|
||||
{
|
||||
Safe(result.Group),
|
||||
Safe(result.MachineName),
|
||||
Safe(result.Description)
|
||||
});
|
||||
}
|
||||
|
||||
private static string FormatCompactStatus(ProbeResult result)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
return "n/a";
|
||||
}
|
||||
|
||||
if (result.IsSkipped)
|
||||
{
|
||||
return "SKIPPED - " + Safe(result.Detail);
|
||||
}
|
||||
|
||||
return (result.IsSuccess ? "UP" : "DOWN") + " - " + Safe(result.Detail);
|
||||
}
|
||||
|
||||
private static string FirstNonEmpty(IEnumerable<string> values)
|
||||
{
|
||||
if (values == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return values.FirstOrDefault(v => !string.IsNullOrWhiteSpace(v)) ?? string.Empty;
|
||||
}
|
||||
|
||||
private static string Safe(string value)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(value) ? "n/a" : value;
|
||||
@@ -329,6 +425,7 @@ namespace HostAvailabilityMonitor.Notifications
|
||||
public int CurrentTargetsDown { get; set; }
|
||||
public int CurrentTargetsSkipped { get; set; }
|
||||
public List<ProbeResult> CurrentFailures { get; set; } = new List<ProbeResult>();
|
||||
public List<ProbeResult> CurrentResults { get; set; } = new List<ProbeResult>();
|
||||
public IDictionary<string, TargetState> CurrentState { get; set; } = new Dictionary<string, TargetState>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace HostAvailabilityMonitor
|
||||
var configPath = args != null && args.Length > 0 && !string.IsNullOrWhiteSpace(args[0])
|
||||
? args[0]
|
||||
: Path.Combine(baseDirectory, "appsettings.json");
|
||||
var fullConfigPath = Path.GetFullPath(configPath);
|
||||
|
||||
var config = MonitorConfiguration.Load(configPath);
|
||||
config.Validate();
|
||||
@@ -43,7 +44,7 @@ namespace HostAvailabilityMonitor
|
||||
logger = new FileLogger(logDirectory, config.Logging.FilePrefix, config.Logging.RetentionDays, config.ApplicationName, config.EnvironmentName);
|
||||
logger.CleanupOldFiles();
|
||||
logger.Info(config.ApplicationName + " gestartet. Umgebung=" + config.EnvironmentName + ", Server=" + Environment.MachineName + ".");
|
||||
logger.Info("Konfiguration geladen: " + Path.GetFullPath(configPath));
|
||||
logger.Info("Konfiguration geladen: " + fullConfigPath);
|
||||
|
||||
eventLogger = new WindowsEventLogger(config.EventLog, logger);
|
||||
eventLogger.TryInitialize();
|
||||
@@ -67,7 +68,7 @@ namespace HostAvailabilityMonitor
|
||||
|
||||
var currentState = new Dictionary<string, TargetState>(previousState, StringComparer.OrdinalIgnoreCase);
|
||||
var probeService = new EndpointProbeService(config.Runtime);
|
||||
var enabledTargets = config.Targets.Where(t => t != null && t.Enabled).ToList();
|
||||
var enabledTargets = BuildEnabledTargets(config, fullConfigPath, baseDirectory, logger);
|
||||
|
||||
if (enabledTargets.Count == 0)
|
||||
{
|
||||
@@ -219,6 +220,126 @@ namespace HostAvailabilityMonitor
|
||||
return results;
|
||||
}
|
||||
|
||||
private static List<TargetOptions> BuildEnabledTargets(MonitorConfiguration config, string configPath, string baseDirectory, FileLogger logger)
|
||||
{
|
||||
var targets = config.Targets == null
|
||||
? new List<TargetOptions>()
|
||||
: config.Targets.Where(t => t != null && t.Enabled).ToList();
|
||||
|
||||
if (config.HipVirtualMachines == null || !config.HipVirtualMachines.Enabled)
|
||||
{
|
||||
return targets;
|
||||
}
|
||||
|
||||
var vmConfigPath = ResolveConfigurationPath(configPath, baseDirectory, config.HipVirtualMachines.ConfigPath);
|
||||
logger.Info("HIP-VM-Konfiguration wird geladen: " + vmConfigPath);
|
||||
|
||||
var vmConfig = HipVirtualMachineConfiguration.Load(vmConfigPath);
|
||||
var vmTargets = CreateHipVirtualMachineTargets(vmConfig, config.HipVirtualMachines, logger);
|
||||
targets.AddRange(vmTargets);
|
||||
|
||||
logger.Info("HIP-VM-Konfiguration geladen. VMs=" + vmConfig.VirtualMachines.Count + ", generierte Targets=" + vmTargets.Count + ".");
|
||||
return targets;
|
||||
}
|
||||
|
||||
private static List<TargetOptions> CreateHipVirtualMachineTargets(HipVirtualMachineConfiguration vmConfig, HipVirtualMachineOptions options, FileLogger logger)
|
||||
{
|
||||
var targets = new List<TargetOptions>();
|
||||
var machines = vmConfig == null || vmConfig.VirtualMachines == null
|
||||
? new List<HipVirtualMachine>()
|
||||
: vmConfig.VirtualMachines;
|
||||
|
||||
foreach (var vm in machines)
|
||||
{
|
||||
if (vm == null || !vm.Enabled)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var address = (vm.Address ?? string.Empty).Trim();
|
||||
if (string.IsNullOrWhiteSpace(address))
|
||||
{
|
||||
logger.Warn("HIP-VM ohne Adresse wurde uebersprungen. Name=" + (vm.Name ?? string.Empty) + ".");
|
||||
continue;
|
||||
}
|
||||
|
||||
var machineName = string.IsNullOrWhiteSpace(vm.Name) ? address : vm.Name.Trim();
|
||||
var applicationName = string.IsNullOrWhiteSpace(options.ApplicationName) ? "HIP Virtual Machines" : options.ApplicationName.Trim();
|
||||
var timeoutSeconds = Math.Max(1, options.TimeoutSeconds);
|
||||
|
||||
if (options.CheckNetwork)
|
||||
{
|
||||
targets.Add(CreateHipVirtualMachineTarget(
|
||||
vm,
|
||||
machineName,
|
||||
applicationName,
|
||||
"Network",
|
||||
"Netzwerk",
|
||||
"icmp://" + address,
|
||||
null,
|
||||
timeoutSeconds));
|
||||
}
|
||||
|
||||
if (options.CheckRdp)
|
||||
{
|
||||
targets.Add(CreateHipVirtualMachineTarget(
|
||||
vm,
|
||||
machineName,
|
||||
applicationName,
|
||||
"RDP",
|
||||
"RDP",
|
||||
"rdp://" + address + ":" + Math.Max(1, options.RdpPort),
|
||||
Math.Max(1, options.RdpPort),
|
||||
timeoutSeconds));
|
||||
}
|
||||
}
|
||||
|
||||
return targets;
|
||||
}
|
||||
|
||||
private static TargetOptions CreateHipVirtualMachineTarget(
|
||||
HipVirtualMachine vm,
|
||||
string machineName,
|
||||
string applicationName,
|
||||
string checkName,
|
||||
string displayCheckName,
|
||||
string endpoint,
|
||||
int? port,
|
||||
int timeoutSeconds)
|
||||
{
|
||||
return new TargetOptions
|
||||
{
|
||||
Name = machineName + " - " + displayCheckName,
|
||||
ApplicationName = applicationName,
|
||||
Endpoint = endpoint,
|
||||
Port = port,
|
||||
TimeoutSeconds = timeoutSeconds,
|
||||
Enabled = true,
|
||||
Source = "HipVirtualMachines",
|
||||
Group = vm.Group,
|
||||
Description = vm.Description,
|
||||
MachineName = machineName,
|
||||
CheckName = checkName
|
||||
};
|
||||
}
|
||||
|
||||
private static string ResolveConfigurationPath(string configPath, string baseDirectory, string configuredPath)
|
||||
{
|
||||
if (Path.IsPathRooted(configuredPath))
|
||||
{
|
||||
return configuredPath;
|
||||
}
|
||||
|
||||
var configDirectory = Path.GetDirectoryName(Path.GetFullPath(configPath));
|
||||
var configRelativePath = Path.GetFullPath(Path.Combine(configDirectory, configuredPath));
|
||||
if (File.Exists(configRelativePath))
|
||||
{
|
||||
return configRelativePath;
|
||||
}
|
||||
|
||||
return Path.GetFullPath(Path.Combine(baseDirectory, configuredPath));
|
||||
}
|
||||
|
||||
private static async Task TrySendDailySummaryAsync(
|
||||
MonitorConfiguration config,
|
||||
EmailNotifier notifier,
|
||||
@@ -258,6 +379,7 @@ namespace HostAvailabilityMonitor
|
||||
CurrentTargetsDown = latestResults.Count(r => !r.IsSkipped && !r.IsSuccess),
|
||||
CurrentTargetsSkipped = latestResults.Count(r => r.IsSkipped),
|
||||
CurrentFailures = currentFailures,
|
||||
CurrentResults = latestResults,
|
||||
CurrentState = currentState
|
||||
};
|
||||
|
||||
@@ -368,11 +490,16 @@ namespace HostAvailabilityMonitor
|
||||
private static string BuildEventMessage(MonitorConfiguration config, ProbeResult result)
|
||||
{
|
||||
return string.Format(
|
||||
"Umgebung={0} | Anwendung={1} | Name={2} | Endpoint={3} | Status={4} | Detail={5}",
|
||||
"Umgebung={0} | Anwendung={1} | Name={2} | Endpoint={3} | Typ={4} | Quelle={5} | Gruppe={6} | Maschine={7} | Check={8} | Status={9} | Detail={10}",
|
||||
config.EnvironmentName,
|
||||
result.ApplicationName,
|
||||
result.Name,
|
||||
result.Endpoint,
|
||||
result.Kind,
|
||||
result.Source,
|
||||
result.Group,
|
||||
result.MachineName,
|
||||
result.CheckName,
|
||||
result.StatusText,
|
||||
result.Detail);
|
||||
}
|
||||
|
||||
@@ -48,6 +48,15 @@
|
||||
"CooldownMinutes": 0,
|
||||
"TimeoutSeconds": 30
|
||||
},
|
||||
"HipVirtualMachines": {
|
||||
"Enabled": true,
|
||||
"ConfigPath": "hip-vms.json",
|
||||
"ApplicationName": "HIP Virtual Machines",
|
||||
"TimeoutSeconds": 5,
|
||||
"RdpPort": 3389,
|
||||
"CheckNetwork": true,
|
||||
"CheckRdp": true
|
||||
},
|
||||
"Targets": [
|
||||
{
|
||||
"Name": "Internes Fileshare 1",
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
{
|
||||
"VirtualMachines": [
|
||||
{
|
||||
"Group": "Entwickermaschinen",
|
||||
"Name": "dv23aasw0001",
|
||||
"Address": "10.121.157.21",
|
||||
"Description": "Developer Machine (Steffen R.)",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "Entwickermaschinen",
|
||||
"Name": "dv23aasw0006",
|
||||
"Address": "10.121.157.27",
|
||||
"Description": "Developer Machine (Johannes Rest)",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "Entwickermaschinen",
|
||||
"Name": "dv23aasw0007",
|
||||
"Address": "10.121.157.28",
|
||||
"Description": "Developer Machine (Reza Takhsha)",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "Entwickermaschinen",
|
||||
"Name": "dv23aasw0002",
|
||||
"Address": "10.121.157.22",
|
||||
"Description": "Developer Machine (Chris Schild)",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "Entwickermaschinen",
|
||||
"Name": "dv23agpwbi01",
|
||||
"Address": "10.121.157.8",
|
||||
"Description": "Developer Machine (Ronny)",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "Entwickermaschinen",
|
||||
"Name": "dv23agpwbi02",
|
||||
"Address": "10.121.157.9",
|
||||
"Description": "Developer Machine (Lars)",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "Entwickermaschinen",
|
||||
"Name": "dv23agpwbi03",
|
||||
"Address": "10.121.157.10",
|
||||
"Description": "BizTalk Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "Entwickermaschinen",
|
||||
"Name": "dv23agpwbi04",
|
||||
"Address": "10.121.157.7",
|
||||
"Description": "Monitoring/Administration Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "Entwickermaschinen",
|
||||
"Name": "dv23adbwbi01",
|
||||
"Address": "10.121.157.6",
|
||||
"Description": "BizTalk DB Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "Entwickermaschinen",
|
||||
"Name": "dv23wgpwbi01",
|
||||
"Address": "10.123.49.100",
|
||||
"Description": "IIS Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "TST",
|
||||
"Name": "tv23agpwbi01",
|
||||
"Address": "10.121.157.11",
|
||||
"Description": "BizTalk Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "TST",
|
||||
"Name": "tv23agpwbi02",
|
||||
"Address": "10.121.157.12",
|
||||
"Description": "Monitoring/Administration Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "TST",
|
||||
"Name": "tv23adbwbi01",
|
||||
"Address": "10.121.157.13",
|
||||
"Description": "BizTalk DB Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "TST",
|
||||
"Name": "tv23wgpwbi01",
|
||||
"Address": "10.123.49.228",
|
||||
"Description": "IIS Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "ACC",
|
||||
"Name": "av23agpwbi01",
|
||||
"Address": "10.121.145.6",
|
||||
"Description": "BizTalk Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "ACC",
|
||||
"Name": "av23agpwbi02",
|
||||
"Address": "10.121.145.7",
|
||||
"Description": "Monitoring/Administration Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "ACC",
|
||||
"Name": "av23adbwbi01",
|
||||
"Address": "10.121.145.8",
|
||||
"Description": "BizTalk DB Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "ACC",
|
||||
"Name": "acc-lbi-23-agw-bewintegration0001",
|
||||
"Address": "10.123.47.198",
|
||||
"Description": "Load Balancer",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "ACC",
|
||||
"Name": "av23wgpwbi01",
|
||||
"Address": "10.123.47.196",
|
||||
"Description": "IIS Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "ACC",
|
||||
"Name": "av23wgpwbi02",
|
||||
"Address": "10.123.47.197",
|
||||
"Description": "IIS Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "Produktion",
|
||||
"Name": "pv23agpwbi01",
|
||||
"Address": "10.121.145.9",
|
||||
"Description": "BizTalk Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "Produktion",
|
||||
"Name": "pv23agpwbi02",
|
||||
"Address": "10.121.145.10",
|
||||
"Description": "Monitoring/Administration Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "Produktion",
|
||||
"Name": "pv23adbwbi01",
|
||||
"Address": "10.121.145.11",
|
||||
"Description": "BizTalk DB Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "Produktion",
|
||||
"Name": "pv23wgpwbi01",
|
||||
"Address": "10.123.48.196",
|
||||
"Description": "IIS Server",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Group": "Produktion",
|
||||
"Name": "pv23wgpwbi02",
|
||||
"Address": "10.123.48.197",
|
||||
"Description": "IIS Server",
|
||||
"Enabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user