public DistributeFileResult DistributeFile(DistributionFile distributionFile) { string errorMessage = null; try { Configuration configuration = Configuration.Read(); Group group = configuration.Groups.FirstOrDefault(x => x.ID == distributionFile.DestinationGroupID); if (group == null) { Logger.AddAndThrow <DistributeFileException>(LogType.Error, $"Could not find group with ID {distributionFile.DestinationGroupID}"); } string filePath = Path.Combine(group.Path, distributionFile.RelativePath.Trim(Path.DirectorySeparatorChar)); try { FileSystemHandler.PutFileContent(filePath, distributionFile.Content); } catch (Exception ex) { Logger.AddAndThrow <DistributeFileException>($"Failed to persist file content of {filePath}", ex); } } catch (DistributeFileException ex) { errorMessage = ex.Message; } return(new DistributeFileResult(distributionFile.RelativePath, distributionFile.DestinationGroupID, errorMessage)); }
public static void Stop(Group group, Application application) { foreach (Process process in GetProcesses(group, application)) { try { process.Kill(); } catch (Exception ex) { Logger.AddAndThrow <ProcessActionException>($"Failed to kill process with path {process.GetPathName()}", ex); } } }
public ProcessActionResult TakeProcessAction(Guid groupID, Guid applicationID, ActionType type) { string errorMessage = null; try { Configuration configuration = Configuration.Read(); Group group = configuration.Groups.FirstOrDefault(x => x.ID == groupID); Application application = configuration.Applications.FirstOrDefault(x => x.ID == applicationID); if (group == null) { Logger.AddAndThrow <ProcessActionException>(LogType.Error, $"Application {type}: Could not find group with ID {groupID}"); } if (application == null) { Logger.AddAndThrow <ProcessActionException>(LogType.Error, $"Application {type}: Could not find application with ID {applicationID}"); } switch (type) { case ActionType.Start: ProcessHandler.Start(group, application); break; case ActionType.Stop: ProcessHandler.Stop(group, application); break; case ActionType.Restart: ProcessHandler.Restart(group, application); break; default: Logger.AddAndThrow <ProcessActionException>(LogType.Error, $"Process action type invalid: {type}"); break; } } catch (ProcessActionException ex) { errorMessage = ex.Message; } return(new ProcessActionResult(type, errorMessage, _processStatuses.ContainsKey(groupID) && _processStatuses[groupID].ContainsKey(applicationID) ? _processStatuses[groupID][applicationID] : null)); }
public DistributionActionResult TakeDistributionAction(string sourceMachineHostName, Guid groupID, Guid applicationID, string destinationMachineHostName, ActionType type, Guid clientId) { string errorMessage = null; try { Configuration configuration = Configuration.Read(); Group group = configuration.Groups.FirstOrDefault(x => x.ID == groupID); Application application = configuration.Applications.FirstOrDefault(x => x.ID == applicationID); if (string.IsNullOrEmpty(sourceMachineHostName)) { Logger.AddAndThrow <DistributionActionException>(LogType.Error, $"Application {type}: Missing source machine host name"); } if (group == null) { Logger.AddAndThrow <DistributionActionException>(LogType.Error, $"Application {type}: Could not find group with ID {groupID}"); } if (application == null) { Logger.AddAndThrow <DistributionActionException>(LogType.Error, $"Application {type}: Could not find application with ID {applicationID}"); } if (string.IsNullOrEmpty(destinationMachineHostName)) { Logger.AddAndThrow <DistributionActionException>(LogType.Error, $"Application {type}: Missing destination machine host name"); } DistributionWorker.Instance.AddWork(new DistributionWork(type, new Machine(sourceMachineHostName), group, application, new Machine(destinationMachineHostName), clientId)); } catch (DistributionActionException ex) { errorMessage = ex.Message; } return(new DistributionActionResult(type, errorMessage)); }
private void DistributeSourceFilesThread(Machine machine) { List <DistributionWork> processedDistributionWork = new List <DistributionWork>(); while (ConnectionStore.ConnectionCreated(machine)) { DistributionWork work; lock (_pendingDistributionWork) { work = _pendingDistributionWork .Where(pendingWork => Comparer.MachinesEqual(pendingWork.DestinationMachine, machine)) .FirstOrDefault(pendingWork => !processedDistributionWork.Contains(pendingWork)); } if (work == null) { Thread.Sleep(10); continue; } processedDistributionWork.Add(work); Task.Run(() => { try { try { Group destinationGroup = ConnectionStore.Connections[work.DestinationMachine].Configuration.Groups .FirstOrDefault(group => Comparer.GroupsEqual(group, work.Group)); if (destinationGroup == null) { Logger.AddAndThrow <DistributionActionException>(LogType.Warning, $"Could not distribute application {work.Application.Name} in group {work.Group.Name}" + $" to destination machine {work.DestinationMachine.HostName}. Destination machine does not contain a matching group."); } List <string> errorMessages = new List <string>(); foreach (DistributionFile file in work.Files) { file.DestinationGroupID = destinationGroup.ID; file.Content = FileSystemHandler.GetFileContent(Path.Combine(work.Group.Path, file.RelativePath.Trim(Path.DirectorySeparatorChar))); DistributeFileResult result = ConnectionStore.Connections[work.DestinationMachine].ServiceHandler.Service.DistributeFile(new DTODistributionFile(file)).FromDTO(); try { if (result.Success) { Logger.Add(LogType.Verbose, $"Distribution of file to {work.DestinationMachine.HostName} succeeded: {file.RelativePath}, {file.Content.Length} bytes"); } else { Logger.AddAndThrow <DistributionActionException>(LogType.Error, $"Distribution of file to {work.DestinationMachine.HostName} failed: {Path.GetFileName(file.RelativePath)} | {result.ErrorMessage}"); } } catch (DistributionActionException ex) { errorMessages.Add(ex.Message); } file.IsDistributed = true; } if (errorMessages.Any()) { throw new DistributionActionException(string.Join(Environment.NewLine, errorMessages.Select(x => x.Replace(" | ", Environment.NewLine + "\t")))); } RaiseDistributionCompletedEvent(new DistributionResult(work, DistributionResultValue.Success), work.ClientId); } catch (DistributionActionException) { throw; } catch (ThreadAbortException) { } catch (Exception ex) { Logger.AddAndThrow <DistributionActionException>("An unexpected error occurred while distributing source files, aborting..", ex); } finally { lock (_pendingDistributionWork) _pendingDistributionWork.Remove(work); } } catch (DistributionActionException ex) { RaiseDistributionCompletedEvent(new DistributionResult(work, DistributionResultValue.Failure, ex.Message), work.ClientId); } }); } }
private static void Start(Group group, Application application, bool waitUntilStopped) { if (waitUntilStopped) { WaitForProcessToTerminate(group, application); } if (ProcessExists(group, application)) { throw new ProcessActionException("Could not start process as it is already running"); } string fullPath = Path.Combine(group.Path, application.RelativePath.TrimStart('\\')); Process process = new Process() { StartInfo = { FileName = fullPath, Arguments = application.Arguments } }; try { process.Start(); } catch (Exception ex) { Logger.AddAndThrow <ProcessActionException>($"Failed to start process with path {fullPath}", ex); } if (!application.WaitForExit) { return; } if (process.WaitForExit(WAIT_FOR_EXIT_TIMEOUT)) { switch (application.SuccessExitCode) { case SuccessExitCode.Zero: if (process.ExitCode != 0) { throw new ProcessActionException($"Process exit code was {process.ExitCode} (expected zero)"); } break; case SuccessExitCode.Positive: if (process.ExitCode < 0) { throw new ProcessActionException($"Process exit code was {process.ExitCode} (expected positive)"); } break; case SuccessExitCode.Negative: if (process.ExitCode >= 0) { throw new ProcessActionException($"Process exit code was {process.ExitCode} (expected negative)"); } break; } } else { throw new ProcessActionException($"Process did not exit within {WAIT_FOR_EXIT_TIMEOUT} milliseconds"); } }