using System.Text.RegularExpressions; using CliWrap; using CliWrap.Buffered; namespace RAIDAlert; public partial class Watchdog : BackgroundService { private const string HpCliUtil = "hpssacli.exe"; private const string PcBeeperUtil = "pc-beeper.exe"; private readonly ILogger _logger; public Watchdog(ILogger logger) { _logger = logger; } [GeneratedRegex(@"physicaldrive \d*I:\d*:\d* \(port \d*I:box \d*:bay \d*, SATA, \d*(?:.\d*)? [GT]B, (.+)\)", RegexOptions.Multiline)] private partial Regex RegexArrayStatus(); protected override async Task ExecuteAsync(CancellationToken stoppingToken) { string workingDirectory = Path.GetDirectoryName(Environment.ProcessPath!)!; string hpSsaCli = Path.Combine(workingDirectory, HpCliUtil); string pcBeeper = Path.Combine(workingDirectory, PcBeeperUtil); // Ready beep sequence await Cli.Wrap(pcBeeper) .WithArguments(new[] { "-f", "1500", "-d", "100" }) .WithWorkingDirectory(workingDirectory) .ExecuteAsync(stoppingToken); await Task.Delay(TimeSpan.FromMilliseconds(10), stoppingToken); await Cli.Wrap(pcBeeper) .WithArguments(new[] { "-f", "2000", "-d", "100" }) .WithWorkingDirectory(workingDirectory) .ExecuteAsync(stoppingToken); while (!stoppingToken.IsCancellationRequested) { // Run "hpssacli" to query disk status BufferedCommandResult hpSsaCliResult = await Cli.Wrap(hpSsaCli) .WithArguments(new[] { "controller", "slot=1", "physicaldrive", "all", "show" }) .WithWorkingDirectory(workingDirectory) .ExecuteBufferedAsync(stoppingToken); MatchCollection matches = RegexArrayStatus().Matches(hpSsaCliResult.StandardOutput); if (matches.Count == 0) { _logger.LogError("Checking for physical disk status yielded no results"); } else { bool allHealthy = matches.All(m => m.Groups[1].Value.Equals("OK", StringComparison.OrdinalIgnoreCase)); if (!allHealthy) { _logger.LogError("One or more disks reported faulty status"); // Make some noise! await Cli.Wrap(pcBeeper) .WithArguments(new[] { "-f", "3000", "-d", "500" }) .WithWorkingDirectory(workingDirectory) .ExecuteAsync(stoppingToken); await Task.Delay(TimeSpan.FromMilliseconds(100), stoppingToken); await Cli.Wrap(pcBeeper) .WithArguments(new[] { "-f", "3000", "-d", "500" }) .WithWorkingDirectory(workingDirectory) .ExecuteAsync(stoppingToken); await Task.Delay(TimeSpan.FromMilliseconds(100), stoppingToken); await Cli.Wrap(pcBeeper) .WithArguments(new[] { "-f", "3000", "-d", "500" }) .WithWorkingDirectory(workingDirectory) .ExecuteAsync(stoppingToken); } } await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken); } } }