From e321769dd4b233e0469e14fb44eb538849f421e1 Mon Sep 17 00:00:00 2001 From: Tudor Stanciu Date: Mon, 10 Jan 2022 09:41:22 +0200 Subject: [PATCH] new services --- .../CommandHandlers/ShutdownHandler.cs | 15 +++-- .../DependencyInjectionExtensions.cs | 17 ++++- .../Mappings/MappingProfile.cs | 4 +- .../Services/Abstractions/ICliService.cs | 7 ++ .../Services/Abstractions/IPowerService.cs | 10 +++ .../Services/Abstractions/IShutdownService.cs | 7 -- .../Services/Linux/BashService.cs | 13 ++++ .../Services/Linux/LinuxPowerService.cs | 19 ++++++ .../Services/ShutdownService.cs | 42 ------------ .../Services/Windows/CmdService.cs | 66 +++++++++++++++++++ .../Services/Windows/WindowsPowerService.cs | 35 ++++++++++ .../Models/Records.cs | 4 ++ 12 files changed, 183 insertions(+), 56 deletions(-) create mode 100644 src/agent/NetworkResurrector.Agent.Application/Services/Abstractions/ICliService.cs create mode 100644 src/agent/NetworkResurrector.Agent.Application/Services/Abstractions/IPowerService.cs delete mode 100644 src/agent/NetworkResurrector.Agent.Application/Services/Abstractions/IShutdownService.cs create mode 100644 src/agent/NetworkResurrector.Agent.Application/Services/Linux/BashService.cs create mode 100644 src/agent/NetworkResurrector.Agent.Application/Services/Linux/LinuxPowerService.cs delete mode 100644 src/agent/NetworkResurrector.Agent.Application/Services/ShutdownService.cs create mode 100644 src/agent/NetworkResurrector.Agent.Application/Services/Windows/CmdService.cs create mode 100644 src/agent/NetworkResurrector.Agent.Application/Services/Windows/WindowsPowerService.cs create mode 100644 src/agent/NetworkResurrector.Agent.Domain/Models/Records.cs diff --git a/src/agent/NetworkResurrector.Agent.Application/CommandHandlers/ShutdownHandler.cs b/src/agent/NetworkResurrector.Agent.Application/CommandHandlers/ShutdownHandler.cs index c481efc..cff6496 100644 --- a/src/agent/NetworkResurrector.Agent.Application/CommandHandlers/ShutdownHandler.cs +++ b/src/agent/NetworkResurrector.Agent.Application/CommandHandlers/ShutdownHandler.cs @@ -1,6 +1,8 @@ -using MediatR; +using AutoMapper; +using MediatR; using Microsoft.Extensions.Logging; using NetworkResurrector.Agent.Application.Services.Abstractions; +using NetworkResurrector.Agent.Domain.Models; using NetworkResurrector.Agent.PublishedLanguage.Commands; using NetworkResurrector.Agent.PublishedLanguage.Events; using System.Diagnostics; @@ -12,14 +14,16 @@ namespace NetworkResurrector.Agent.Application.CommandHandlers public class ShutdownHandler : IRequestHandler { private readonly ILogger _logger; - private readonly IShutdownService _shutdownService; + private readonly IPowerService _powerService; private readonly IValidationService _validationService; + private readonly IMapper _mapper; - public ShutdownHandler(ILogger logger, IShutdownService shutdownService, IValidationService validationService) + public ShutdownHandler(ILogger logger, IPowerService powerService, IValidationService validationService, IMapper mapper) { _logger=logger; - _shutdownService=shutdownService; + _powerService=powerService; _validationService=validationService; + _mapper=mapper; } public async Task Handle(Shutdown command, CancellationToken cancellationToken) @@ -36,7 +40,8 @@ namespace NetworkResurrector.Agent.Application.CommandHandlers var stopWatch = new Stopwatch(); stopWatch.Start(); - _shutdownService.Run(); + var options = _mapper.Map(command.Options); + _powerService.Shutdown(options); stopWatch.Stop(); _logger.LogDebug($"System shutdown finished - {stopWatch.ElapsedMilliseconds:N0} ms"); diff --git a/src/agent/NetworkResurrector.Agent.Application/DependencyInjectionExtensions.cs b/src/agent/NetworkResurrector.Agent.Application/DependencyInjectionExtensions.cs index 0a73d65..47e26d9 100644 --- a/src/agent/NetworkResurrector.Agent.Application/DependencyInjectionExtensions.cs +++ b/src/agent/NetworkResurrector.Agent.Application/DependencyInjectionExtensions.cs @@ -1,6 +1,10 @@ using Microsoft.Extensions.DependencyInjection; using NetworkResurrector.Agent.Application.Services; using NetworkResurrector.Agent.Application.Services.Abstractions; +using NetworkResurrector.Agent.Application.Services.Linux; +using NetworkResurrector.Agent.Application.Services.Windows; +using System; +using System.Runtime.InteropServices; namespace NetworkResurrector.Agent.Application { @@ -10,7 +14,18 @@ namespace NetworkResurrector.Agent.Application { services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + services.AddSingleton(); + services.AddSingleton(); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + services.AddSingleton(); + services.AddSingleton(); + } + else throw new Exception("Cannot register IPowerService. Unknown operating system."); } } } diff --git a/src/agent/NetworkResurrector.Agent.Application/Mappings/MappingProfile.cs b/src/agent/NetworkResurrector.Agent.Application/Mappings/MappingProfile.cs index ea18817..694ee8c 100644 --- a/src/agent/NetworkResurrector.Agent.Application/Mappings/MappingProfile.cs +++ b/src/agent/NetworkResurrector.Agent.Application/Mappings/MappingProfile.cs @@ -1,4 +1,6 @@ using AutoMapper; +using NetworkResurrector.Agent.Domain.Models; +using NetworkResurrector.Agent.PublishedLanguage.Dto; namespace NetworkResurrector.Agent.Application.Mappings { @@ -6,7 +8,7 @@ namespace NetworkResurrector.Agent.Application.Mappings { public MappingProfile() { - //CreateMap(); + CreateMap(); } } } diff --git a/src/agent/NetworkResurrector.Agent.Application/Services/Abstractions/ICliService.cs b/src/agent/NetworkResurrector.Agent.Application/Services/Abstractions/ICliService.cs new file mode 100644 index 0000000..07c6f2b --- /dev/null +++ b/src/agent/NetworkResurrector.Agent.Application/Services/Abstractions/ICliService.cs @@ -0,0 +1,7 @@ +namespace NetworkResurrector.Agent.Application.Services.Abstractions +{ + public interface ICliService + { + (bool success, string message) Execute(string command); + } +} diff --git a/src/agent/NetworkResurrector.Agent.Application/Services/Abstractions/IPowerService.cs b/src/agent/NetworkResurrector.Agent.Application/Services/Abstractions/IPowerService.cs new file mode 100644 index 0000000..96601c2 --- /dev/null +++ b/src/agent/NetworkResurrector.Agent.Application/Services/Abstractions/IPowerService.cs @@ -0,0 +1,10 @@ +using NetworkResurrector.Agent.Domain.Models; + +namespace NetworkResurrector.Agent.Application.Services.Abstractions +{ + public interface IPowerService + { + void Shutdown(PowerOptions options); + void Lock(); + } +} diff --git a/src/agent/NetworkResurrector.Agent.Application/Services/Abstractions/IShutdownService.cs b/src/agent/NetworkResurrector.Agent.Application/Services/Abstractions/IShutdownService.cs deleted file mode 100644 index 427cb6e..0000000 --- a/src/agent/NetworkResurrector.Agent.Application/Services/Abstractions/IShutdownService.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace NetworkResurrector.Agent.Application.Services.Abstractions -{ - public interface IShutdownService - { - void Run(); - } -} diff --git a/src/agent/NetworkResurrector.Agent.Application/Services/Linux/BashService.cs b/src/agent/NetworkResurrector.Agent.Application/Services/Linux/BashService.cs new file mode 100644 index 0000000..56c5dd1 --- /dev/null +++ b/src/agent/NetworkResurrector.Agent.Application/Services/Linux/BashService.cs @@ -0,0 +1,13 @@ +using NetworkResurrector.Agent.Application.Services.Abstractions; +using System; + +namespace NetworkResurrector.Agent.Application.Services.Linux +{ + internal class BashService : ICliService + { + public (bool success, string message) Execute(string command) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/agent/NetworkResurrector.Agent.Application/Services/Linux/LinuxPowerService.cs b/src/agent/NetworkResurrector.Agent.Application/Services/Linux/LinuxPowerService.cs new file mode 100644 index 0000000..745cc85 --- /dev/null +++ b/src/agent/NetworkResurrector.Agent.Application/Services/Linux/LinuxPowerService.cs @@ -0,0 +1,19 @@ +using NetworkResurrector.Agent.Application.Services.Abstractions; +using NetworkResurrector.Agent.Domain.Models; +using System; + +namespace NetworkResurrector.Agent.Application.Services.Linux +{ + internal class LinuxPowerService : IPowerService + { + public void Shutdown(PowerOptions options) + { + throw new NotImplementedException(); + } + + public void Lock() + { + throw new NotImplementedException(); + } + } +} diff --git a/src/agent/NetworkResurrector.Agent.Application/Services/ShutdownService.cs b/src/agent/NetworkResurrector.Agent.Application/Services/ShutdownService.cs deleted file mode 100644 index 683d270..0000000 --- a/src/agent/NetworkResurrector.Agent.Application/Services/ShutdownService.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Microsoft.Extensions.Logging; -using NetworkResurrector.Agent.Application.Services.Abstractions; -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace NetworkResurrector.Agent.Application.Services -{ - internal class ShutdownService : IShutdownService - { - private readonly ILogger _logger; - - public ShutdownService(ILogger logger) - { - _logger=logger; - } - - public void Run() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - ShutdownWindows(); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - // Do something - } - else throw new Exception("ShutdownService: Cannot shutdown host. Unknown operating system."); - } - - private void ShutdownWindows() - { - var psi = new ProcessStartInfo("shutdown", "/s /t 0") - { - CreateNoWindow = true, - UseShellExecute = false - }; - - Process.Start(psi); - } - } -} diff --git a/src/agent/NetworkResurrector.Agent.Application/Services/Windows/CmdService.cs b/src/agent/NetworkResurrector.Agent.Application/Services/Windows/CmdService.cs new file mode 100644 index 0000000..a2ffe4b --- /dev/null +++ b/src/agent/NetworkResurrector.Agent.Application/Services/Windows/CmdService.cs @@ -0,0 +1,66 @@ +using Microsoft.Extensions.Logging; +using NetworkResurrector.Agent.Application.Services.Abstractions; +using System; +using System.Diagnostics; +using System.Text; + +namespace NetworkResurrector.Agent.Application.Services.Windows +{ + internal class CmdService : ICliService + { + private readonly ILogger _logger; + + public CmdService(ILogger logger) + { + _logger=logger; + } + + public (bool success, string message) Execute(string command) + { + var msg = new StringBuilder(); + var commandOutput = new StringBuilder(); + var commandError = new StringBuilder(); + + var process = new Process(); + process.StartInfo.RedirectStandardError = true; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.RedirectStandardInput = true; + process.StartInfo.CreateNoWindow = true; + process.StartInfo.UseShellExecute = false; + process.StartInfo.FileName = "cmd.exe"; + + commandOutput.Clear(); + commandError.Clear(); + + process.OutputDataReceived += new DataReceivedEventHandler( + (s, e) => + { + if (!string.IsNullOrEmpty(e.Data)) + commandOutput.Append(e.Data + "\n"); + }); + process.ErrorDataReceived += new DataReceivedEventHandler( + (s, e) => + { + if (!string.IsNullOrEmpty(e.Data)) + commandError.Append(e.Data + "\n"); + }); + + msg.Append($"\nProcess started at: {DateTime.Now}\n"); + process.Start(); + process.StandardInput.WriteLine(command); + process.StandardInput.Flush(); + process.StandardInput.Close(); + + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + + process.WaitForExit(); + msg.Append($"Output:\n {commandOutput.ToString()}\n"); + msg.Append($"Errors:\n {commandError.ToString()}\n"); + msg.Append($"Process ended at: {DateTime.Now}"); + _logger.LogDebug($"Command: {command} | ExecutionLog: {msg}"); + + return (commandError.Length > 0, msg.ToString()); + } + } +} diff --git a/src/agent/NetworkResurrector.Agent.Application/Services/Windows/WindowsPowerService.cs b/src/agent/NetworkResurrector.Agent.Application/Services/Windows/WindowsPowerService.cs new file mode 100644 index 0000000..828153b --- /dev/null +++ b/src/agent/NetworkResurrector.Agent.Application/Services/Windows/WindowsPowerService.cs @@ -0,0 +1,35 @@ +using Microsoft.Extensions.Logging; +using NetworkResurrector.Agent.Application.Services.Abstractions; +using NetworkResurrector.Agent.Domain.Models; +using System.Diagnostics; + +namespace NetworkResurrector.Agent.Application.Services.Windows +{ + internal class WindowsPowerService : IPowerService + { + private readonly ILogger _logger; + private readonly ICliService _cliService; + + public WindowsPowerService(ILogger logger) + { + _logger=logger; + } + + public void Shutdown(PowerOptions options) + { + + var psi = new ProcessStartInfo("shutdown", "/s /t 0") + { + CreateNoWindow = true, + UseShellExecute = false + }; + + Process.Start(psi); + } + + public void Lock() + { + var (success, message) = _cliService.Execute("rundll32.exe user32.dll,LockWorkStation"); + } + } +} diff --git a/src/agent/NetworkResurrector.Agent.Domain/Models/Records.cs b/src/agent/NetworkResurrector.Agent.Domain/Models/Records.cs new file mode 100644 index 0000000..eeff596 --- /dev/null +++ b/src/agent/NetworkResurrector.Agent.Domain/Models/Records.cs @@ -0,0 +1,4 @@ +namespace NetworkResurrector.Agent.Domain.Models +{ + public record PowerOptions(int Delay, bool Force); +}