/// <summary> /// Sets up up Host target and checks for missing params /// Common code used by all CM commands, but specific to this host /// </summary> /// <param name="target">The HostType to target</param> /// <returns>The target Host/Cm, validated</returns> internal override sealed VibesHost SetTargetHost(object target) { VibesHost hostToPoll = null; switch (target) { case HostTypes.EXEC: CheckHostParameters(SelectedHostExec); hostToPoll = SelectedHostExec; break; case HostTypes.OPERDB: CheckHostParameters(SelectedHostOperDb); hostToPoll = SelectedHostOperDb; break; case HostTypes.OPERAPP1: CheckHostParameters(SelectedHostOperAppOne); hostToPoll = SelectedHostOperAppOne; break; case HostTypes.OPERAPP2: CheckHostParameters(SelectedHostOperAppTwo); hostToPoll = SelectedHostOperAppTwo; break; case HostTypes.MS: CheckHostParameters(SelectedHostMs); hostToPoll = SelectedHostMs; break; } return(hostToPoll); }
/// <summary> /// Setups up Host/CM target and checks for missing params /// Common code used by all CM commands, but spefcific to this host /// </summary> /// <param name="target">The HostType to target</param> /// <returns>Tuple containing the target Host/Cm, validated</returns> internal override sealed (VibesHost, VibesCm, ObservableCollection <VibesCm>) SetTargets(object target) { VibesHost hostToPoll = null; VibesCm cmToPoll = null; ObservableCollection <VibesCm> cms = null; switch (target) { case HostTypes.COMM1: CheckSingleParameters(SelectedHostCommOne, SelectedCmCommOne); hostToPoll = SelectedHostCommOne; cmToPoll = SelectedCmCommOne; cms = CmsDisplayCommOne; break; case HostTypes.COMM2: CheckSingleParameters(SelectedHostCommTwo, SelectedCmCommTwo); hostToPoll = SelectedHostCommTwo; cmToPoll = SelectedCmCommTwo; cms = CmsDisplayCommTwo; break; } return(hostToPoll, cmToPoll, cms); }
/// <summary> /// Gets deployment.properties from specified CM /// </summary> /// <param name="host">The host on which the CM is installed</param> /// <param name="cm">The CM to query</param> /// <param name="hashCode">The hash of the sending VM</param> public static void GetCmParams(VibesHost host, VibesCm cm, int hashCode) { ValidateParameters(host, cm); string sshCommand = SshCommands.EchoCmProperties(cm); Task <string> sshResult = Task.Run(() => ExecuteSshCommand(host, sshCommand)); OnCmCommandComplete(host, cm, sshResult.Result, hashCode: hashCode); }
/// <summary> /// Get hosts file from specified host /// </summary> /// <param name="host">The host to query</param> /// <param name="hashCode">The hash of the sending VM</param> public static void GetHostsFile(VibesHost host, int hashCode) { ValidateParameters(host); string sshCommand = SshCommands.EchoRemoteHostsFile(); Task <string> sshResult = Task.Run(() => ExecuteSshCommand(host, sshCommand)); OnCmCommandComplete(host, sshResult.Result, hashCode: hashCode); }
/// <summary> /// Uses SSH command to start remote CM /// Will send back OnCmCommandComplete to all subscribed VM's /// </summary> /// <param name="host">The VibesHost to connect to</param> /// <param name="cm">The VibesCm to start</param> /// <param name="hashCode">The hash of the sending VM</param> public static void StartCm(VibesHost host, VibesCm cm, int hashCode) { ValidateParameters(host, cm); string sshCommand = SshCommands.StartRemoteCmCommand(host, cm); string sshResult = ExecuteSshCommand(host, sshCommand); OnCmCommandComplete(cm, sshResult.Contains("running") ? HttpStatusCode.OK : HttpStatusCode.ServiceUnavailable, hashCode: hashCode); }
/// <summary> /// Polls CM asyncronously from code /// An event is expected back on poll complete, which requires subscribing to CmHttpHelper.PollComplete, in order to update the GUI /// </summary> /// <param name="cmToPoll">Reference to CM to be polled</param> internal void PollCmAsync(VibesCm cmToPoll) { using (DataContext context = new DataContext()) { VibesHost hostToPoll = context.EnvironmentHosts.Single(h => h.Id == cmToPoll.VibesHostId); Task.Run(() => CmHttpHelper.CheckCmStatus(hostToPoll, cmToPoll, GetHashCode())); cmToPoll.CmStatus = CmStates.Polling; } }
/// <summary> /// Switch hosts file on the specified host /// </summary> /// <param name="host">The host to swittch hosts file on</param> /// <param name="indMoveToProd">True if moving from hlcint to prod, false for opposite</param> public static void SwitchHostsFile(VibesHost host, bool indMoveToProd, int hashCode) { ValidateParameters(host, null); string sshCommand = SshCommands.SwitchRemoteHostsFile(host, indMoveToProd); Task.Run(() => { ExecuteSshCommand(host, sshCommand); // Get hostsfile after switch GetHostsFile(host, hashCode); }); }
/// <summary> /// Sets up up Host/CM target and checks for missing params /// Common code used by all CM commands, but specific to this host /// </summary> /// <param name="target">The HostType to target</param> /// <returns>Tuple containing the target Host/Cm, validated</returns> internal override sealed (VibesHost, VibesCm, ObservableCollection <VibesCm>) SetTargets(object target) { VibesHost hostToPoll = null; VibesCm cmToPoll = null; ObservableCollection <VibesCm> cms = null; switch (target) { case HostTypes.EXEC: CheckSingleParameters(SelectedHostExec, SelectedCmExec); hostToPoll = SelectedHostExec; cmToPoll = SelectedCmExec; cms = CmsDisplayExec; break; case HostTypes.OPERDB: CheckSingleParameters(SelectedHostOperDb, SelectedCmOperDb); hostToPoll = SelectedHostOperDb; cmToPoll = SelectedCmOperDb; cms = CmsDisplayOperDb; break; case HostTypes.OPERAPP1: CheckSingleParameters(SelectedHostOperAppOne, SelectedCmOperAppOne); hostToPoll = SelectedHostOperAppOne; cmToPoll = SelectedCmOperAppOne; cms = CmsDisplayOperAppOne; break; case HostTypes.OPERAPP2: CheckSingleParameters(SelectedHostOperAppTwo, SelectedCmOperAppTwo); hostToPoll = SelectedHostOperAppTwo; cmToPoll = SelectedCmOperAppTwo; cms = CmsDisplayOperAppTwo; break; case HostTypes.MS: CheckSingleParameters(SelectedHostMs, SelectedCmMs); hostToPoll = SelectedHostMs; cmToPoll = SelectedCmMs; cms = CmsDisplayMs; break; } return(hostToPoll, cmToPoll, cms); }
/// <summary> /// Uses bash sed command to edit deployment properties file /// Will send back OnCmCommandCOmplete to all subscribed VM's /// </summary> /// <param name="host">The VibesHost to conenct to</param> /// <param name="cm">The VibesCm to edit</param> /// <param name="paramToEdit">The text pattern to find</param> /// <param name="paramToReplace">The text pattern to replace with</param> /// <param name="hashCode">The hash of the sending VM</param> public static void AlterCm(VibesHost host, VibesCm cm, string paramToEdit, string paramToReplace, int hashCode) { ValidateParameters(host, cm); if (string.IsNullOrEmpty(paramToEdit) || string.IsNullOrEmpty(paramToReplace)) { throw new ArgumentNullException($"Attempted to alter CM {cm.CmResourceName} without parameters to add/remove"); } string sshCommand = SshCommands.AlterRemoteCmCommand(host, cm, paramToEdit, paramToReplace); ExecuteSshCommand(host, sshCommand); OnCmCommandComplete(cm, HttpStatusCode.NoContent, hashCode: hashCode); }
/// <summary> /// Validates host/cm parameters to ensure command success /// </summary> /// <param name="host">The host for which parameters need validating</param> /// <param name="cm">Optional, the CM for which parameters need validating</param> private static void ValidateParameters(VibesHost host, VibesCm cm = null) { if (string.IsNullOrEmpty(host.Url)) { throw new ArgumentNullException("Attempted to command CM without URL"); } if (string.IsNullOrEmpty(host.SshUsername) || string.IsNullOrEmpty(host.SshPassword)) { throw new ArgumentNullException("Attempted to command CM without SSH credentials"); } if (cm != null && (string.IsNullOrEmpty(cm.CmCorePath) || string.IsNullOrEmpty(cm.CmPath) || string.IsNullOrEmpty(cm.CmResourceName))) { throw new ArgumentNullException("Attempted to command CM without CM metadata"); } }
/// <summary> /// USes SSH commands to start multiple remote CM's /// Will send back OnCmCommandCOmplete to all subscribed VM's for each applicable CM /// </summary> /// <param name="host">The VibesHost to connect to</param> /// <param name="cms">List of VibesCm's to start</param> /// <param name="hashCode">The hash of the sending VM</param> public static void StartCmMultiple(VibesHost host, List <VibesCm> cms, int hashCode) { ValidateParameters(host); List <(VibesCm, string command)> commands = new List <(VibesCm, string)>(); foreach (VibesCm cm in cms) { string sshCommand = SshCommands.StartRemoteCmCommand(host, cm); commands.Add((cm, sshCommand)); } var results = Task.Run(() => ExecuteMultipleSshCommand(host, commands)); foreach (var result in results.Result) { OnCmCommandComplete(result.cm, result.result.Contains("running") ? HttpStatusCode.OK : HttpStatusCode.ServiceUnavailable, hashCode: hashCode); } }
/// <summary> /// Gets deployment.properties for a list of supplied CM's /// </summary> /// <param name="host">The host on which the CM is installed</param> /// <param name="cms">The CM to query</param> /// <param name="hashCode">The has of the sending VM</param> public static void GetAllCmParams(VibesHost host, List <VibesCm> cms, int hashCode) { ValidateParameters(host); List <(VibesCm, string command)> commands = new List <(VibesCm, string)>(); foreach (VibesCm cm in cms) { string sshCommand = SshCommands.EchoCmProperties(cm); commands.Add((cm, sshCommand)); } var results = Task.Run(() => ExecuteMultipleSshCommand(host, commands)); foreach (var result in results.Result) { OnCmCommandComplete(result.host, result.cm, result.result, hashCode: hashCode); } }
/// <summary> /// Executes supplied SSH command on the supplied host /// </summary> /// <param name="host">The host to send the command</param> /// <param name="sshCommand">The command to execute</param> /// <returns>Any console outtput resulting from the command</returns> private static string ExecuteSshCommand(VibesHost host, string sshCommand) { string result = string.Empty; // Authentication instance.SshPassword = host.SshPassword; KeyboardInteractiveAuthenticationMethod keybAuth = new KeyboardInteractiveAuthenticationMethod(host.SshUsername); keybAuth.AuthenticationPrompt += new EventHandler <AuthenticationPromptEventArgs>(HandleKeyEvent); // Connection Info ConnectionInfo connInfo = new ConnectionInfo(host.Url, 22, host.SshUsername, keybAuth); try { using (SshClient client = new SshClient(connInfo)) { client.Connect(); if (client.IsConnected) { SshCommand command = client.CreateCommand(sshCommand); Log.Debug($"Sending single SSH command {command.CommandText} to {host.Name}"); result = command.Execute(); Log.Debug($"Received single SSH result {result}"); } else { Log.Error($"Error sending SSH command, client not connected"); } client.Disconnect(); } } catch (Exception ex) { Log.Error($"Error sending SSH command, error: {ex.Message}"); } return(result); }
/// <summary> /// Sets up up Host target and checks for missing params /// Common code used by all CM commands, but specific to this host /// </summary> /// <param name="target">The HostType to target</param> /// <returns>The target Host/Cm, validated</returns> internal override sealed VibesHost SetTargetHost(object target) { VibesHost hostToPoll = null; switch (target) { case HostTypes.COMM1: CheckHostParameters(SelectedHostCommOne); hostToPoll = SelectedHostCommOne; break; case HostTypes.COMM2: CheckHostParameters(SelectedHostCommTwo); hostToPoll = SelectedHostCommTwo; break; } return(hostToPoll); }
/// <summary> /// Uses bash sed command to edit multiple deployment properties files /// Will send back OnCmCommandCOmplete to all subscribed VM's for each applicable CM /// </summary> /// <param name="host">The VibesHost to conenct to</param> /// <param name="cm">The VibesCm to edit</param> /// <param name="paramToEdit">The text pattern to find</param> /// <param name="paramToReplace">The text pattern to replace with</param> /// <param name="hashCode">The hash of the sending VM</param> public static void AlterCmMultiple(VibesHost host, List <VibesCm> cms, int hashCode) { ValidateParameters(host); List <(VibesCm, string command)> commands = new List <(VibesCm, string)>(); foreach (VibesCm cm in cms) { foreach (DeploymentProperty propertyToChange in cm.DeploymentProperties) { if (string.IsNullOrEmpty(propertyToChange.SearchPattern) || string.IsNullOrEmpty(propertyToChange.ReplacePattern)) { continue; } string sshCommand = SshCommands.AlterRemoteCmCommand(host, cm, propertyToChange.SearchPattern, propertyToChange.ReplacePattern); commands.Add((cm, sshCommand)); } } var results = Task.Run(() => ExecuteMultipleSshCommand(host, commands)); foreach (var result in results.Result) { OnCmCommandComplete(result.cm, HttpStatusCode.NoContent, hashCode: hashCode); } }
/// <summary> /// Sends a list of commands to the specified host /// </summary> /// <param name="host"></param> /// <param name="commands"></param> /// <returns></returns> private static List <(VibesHost host, VibesCm cm, string result)> ExecuteMultipleSshCommand(VibesHost host, List <(VibesCm cm, string command)> commands)
/// <summary> /// Raises CmCommandComplete event for command resulting from an SSH command which fetches a hosts file /// </summary> /// <param name="hostFetched">The host that was queried</param> /// <param name="hostsFile">The hosts file fetched</param> /// /// <param name="hashCode">The hashcode of the sender</param> private static void OnCmCommandComplete(VibesHost hostFetched, string hostsFile, int hashCode) { CmCommandComplete?.Invoke(null, new CmHelperEventArgs { Host = hostFetched, HostsFile = hostsFile, SubscriberHashCode = hashCode }); }
/// <summary> /// Raises CmCommandComplete event for command resulting from an SSH command which fetches deployment.properties /// </summary> /// <param name="cmChanged">The CM which was changed</param> /// <param name="deploymentProperties">The deployment.properties fetched</param> /// /// <param name="hashCode">The hashcode of the sender</param> private static void OnCmCommandComplete(VibesHost targetHost, VibesCm targetCm, string deploymentProperties, int hashCode) { CmCommandComplete?.Invoke(null, new CmHelperEventArgs { Host = targetHost, CmChanged = targetCm, CmStatus = HttpStatusCode.Continue, DeploymentProperties = deploymentProperties, SubscriberHashCode = hashCode }); }
/// <summary> /// Command to stop a remote CM /// </summary> /// <param name="host">The host the CM sits on, for password and/or clustering</param> /// <param name="cm">The CM to stop</param> /// <returns>SSH command for this host/CM</returns> internal static string StopRemoteCmCommand(VibesHost host, VibesCm cm) { return(host.IndClustered ? $"echo '{host.SshPassword}' | sudo -S /usr/sbin/crm resource stop {cm.CmResourceName}" : $"echo '{host.SshPassword}' | sudo -Su vibes sh {cm.CmCorePath}/bin/cm_stop -i {cm.CmResourceName}"); }
/// <summary> /// Command to alter a remote CM /// </summary> /// <param name="host">The host the CM sits on, for password and/or clustering</param> /// <param name="cm">The CM to alter</param> /// <param name="paramToEdit">The sed search pattern</param> /// <param name="paramToReplace">The sed replace pattern</param> /// <returns>SSH command for this host/CM</returns> internal static string AlterRemoteCmCommand(VibesHost host, VibesCm cm, string paramToEdit, string paramToReplace) { return($"echo '{host.SshPassword}' | sudo -S sed -i 's${paramToEdit}${paramToReplace}$' {cm.CmPath}/conf/deployment.properties"); }
/// <summary> /// Command to swtich remote hosts file /// </summary> /// <param name="host">The host to target, for password</param> /// <param name="indMoveToProd">True if moving to yvr.com DNS, otherwise false</param> /// <returns>SSH command to switch remote hosts file</returns> internal static string SwitchRemoteHostsFile(VibesHost host, bool indMoveToProd) { return(indMoveToProd ? $"echo '{ host.SshPassword }' | sudo -S cp /etc/hosts.prod /etc/hosts" : $"echo '{ host.SshPassword }' | sudo -S cp /etc/hosts.hlcint /etc/hosts"); }
/// <summary> /// Load data from database /// </summary> /// <param name="parameter">Not used, only for GUI binding</param> private void LoadData(object parameter) { try { // Single CM is updated, only update that one CM using (DataContext context = new DataContext()) { if (parameter is VibesCm cmChanged) { VibesCm newCm = context.HostCms.Where(c => c.Id == cmChanged.Id).Include(c => c.DeploymentProperties).Include(c => c.VibesHost).FirstOrDefault().DeepCopy(); newCm.CmStatus = CmStates.Updated; if (CmsDisplayExec.Contains(cmChanged)) { CmsDisplayExec.Remove(CmsDisplayExec.Single(c => c.Id == cmChanged.Id)); CmsDisplayExec.Add(newCm); SelectedCmExec = newCm; SelectedHostExec = HostsDisplayExec.SingleOrDefault(h => h.Id == newCm.VibesHost.Id); } if (CmsDisplayOperDb.Contains(cmChanged)) { CmsDisplayOperDb.Remove(CmsDisplayOperDb.Single(c => c.Id == cmChanged.Id)); CmsDisplayOperDb.Add(newCm); SelectedCmOperDb = newCm; SelectedHostOperDb = HostsDisplayOperDb.SingleOrDefault(h => h.Id == newCm.VibesHost.Id); } if (CmsDisplayOperAppOne.Contains(cmChanged)) { CmsDisplayOperAppOne.Remove(CmsDisplayOperAppOne.Single(c => c.Id == cmChanged.Id)); CmsDisplayOperAppOne.Add(newCm); SelectedCmOperAppOne = newCm; SelectedHostOperAppOne = HostsDisplayOperAppOne.SingleOrDefault(h => h.Id == newCm.VibesHost.Id); } if (CmsDisplayOperAppTwo.Contains(cmChanged)) { CmsDisplayOperAppTwo.Remove(CmsDisplayOperAppTwo.Single(c => c.Id == cmChanged.Id)); CmsDisplayOperAppTwo.Add(newCm); SelectedCmOperAppTwo = newCm; SelectedHostOperAppTwo = HostsDisplayOperAppTwo.SingleOrDefault(h => h.Id == newCm.VibesHost.Id); } if (CmsDisplayMs.Contains(cmChanged)) { CmsDisplayMs.Remove(CmsDisplayMs.Single(c => c.Id == cmChanged.Id)); CmsDisplayMs.Add(newCm); SelectedCmMs = newCm; SelectedHostMs = HostsDisplayMs.SingleOrDefault(h => h.Id == newCm.VibesHost.Id); } return; } } // Initial Load using (DataContext context = new DataContext()) { HostsDisplayExec.Clear(); CmsDisplayExec.Clear(); if (context.EnvironmentHosts.Any(h => h.HostType == HostTypes.EXEC)) { foreach (VibesHost host in context.EnvironmentHosts.Where(h => h.HostType == HostTypes.EXEC).OrderBy(h => h.Name)) { VibesHost newHost = host.DeepCopy(); HostsDisplayExec.Add(newHost); } SelectedHostExec = HostsDisplayExec.FirstOrDefault(); } HostsDisplayOperDb.Clear(); CmsDisplayOperDb.Clear(); if (context.EnvironmentHosts.Any(h => h.HostType == HostTypes.OPERDB)) { foreach (VibesHost host in context.EnvironmentHosts.Where(h => h.HostType == HostTypes.OPERDB).OrderBy(h => h.Name)) { VibesHost newHost = host.DeepCopy(); HostsDisplayOperDb.Add(newHost); } SelectedHostOperDb = HostsDisplayOperDb.FirstOrDefault(); } HostsDisplayOperAppOne.Clear(); CmsDisplayOperAppOne.Clear(); if (context.EnvironmentHosts.Any(h => h.HostType == HostTypes.OPERAPP1)) { foreach (VibesHost host in context.EnvironmentHosts.Where(h => h.HostType == HostTypes.OPERAPP1).OrderBy(h => h.Name)) { VibesHost newHost = host.DeepCopy(); HostsDisplayOperAppOne.Add(newHost); } SelectedHostOperAppOne = HostsDisplayOperAppOne.FirstOrDefault(); } HostsDisplayOperAppTwo.Clear(); CmsDisplayOperAppTwo.Clear(); if (context.EnvironmentHosts.Any(h => h.HostType == HostTypes.OPERAPP2)) { foreach (VibesHost host in context.EnvironmentHosts.Where(h => h.HostType == HostTypes.OPERAPP2).OrderBy(h => h.Name)) { VibesHost newHost = host.DeepCopy(); HostsDisplayOperAppTwo.Add(newHost); } SelectedHostOperAppTwo = HostsDisplayOperAppTwo.FirstOrDefault(); } HostsDisplayMs.Clear(); CmsDisplayMs.Clear(); if (context.EnvironmentHosts.Any(h => h.HostType == HostTypes.MS)) { foreach (VibesHost host in context.EnvironmentHosts.Where(h => h.HostType == HostTypes.MS).OrderBy(h => h.Name)) { VibesHost newHost = host.DeepCopy(); HostsDisplayMs.Add(newHost); } SelectedHostMs = HostsDisplayMs.FirstOrDefault(); } } } catch (Exception ex) { LogAndReportException(ex, $"Error loading VIBES host's from DB: {ex.Message}", true); } }
/// <summary> /// Autosave CM changes when PropertyChanged fires, used to save objects on keypress /// </summary> /// <param name="sender">The object changed</param> /// <param name="args">Propertychanged args</param> internal void PersistTargetChanges(object sender, PropertyChangedEventArgs args) { // Stop execution if sender is VM if (sender is SetupVm || sender is VibesCmSwapVm || sender is EcSwapVm) { return; } try { // Host on setup page if (sender is VibesHost newHostValues) { using (DataContext context = new DataContext()) { VibesHost hostToUpdate = context.EnvironmentHosts.Single(h => h.Id == newHostValues.Id); hostToUpdate.Name = newHostValues.Name ?? hostToUpdate.Name; hostToUpdate.Url = newHostValues.Url ?? hostToUpdate.Url; hostToUpdate.SshUsername = newHostValues.SshUsername ?? hostToUpdate.SshUsername; hostToUpdate.SshPassword = newHostValues.SshPassword ?? hostToUpdate.SshPassword; hostToUpdate.HostType = newHostValues.HostType; hostToUpdate.IndClustered = newHostValues.IndClustered; context.SaveChanges(); } } // CM on setup page else if (sender is VibesCm newCmValues) { using (DataContext context = new DataContext()) { VibesCm cmToUpdate = context.HostCms.Single(c => c.Id == newCmValues.Id); cmToUpdate.CmResourceName = newCmValues.CmResourceName ?? cmToUpdate.CmResourceName; cmToUpdate.CmPort = newCmValues.CmPort ?? cmToUpdate.CmPort; cmToUpdate.CmPath = newCmValues.CmPath ?? cmToUpdate.CmPath; cmToUpdate.CmCorePath = newCmValues.CmCorePath ?? cmToUpdate.CmCorePath; cmToUpdate.CmType = newCmValues.CmType; context.SaveChanges(); } } // CM deployment properties on swap page else if (sender is DeploymentProperty property) { Log.Information($"PropertyChanged Called, sender is {property.PropertyKey} and CM is {property.Cm.CmResourceName}"); using (DataContext context = new DataContext()) { if (context.HostCms.Any(p => p.Id == property.CmId)) { DeploymentProperty propToUpdate = context.DeploymentProperties.SingleOrDefault(p => p.Id == property.Id); propToUpdate.SearchPattern = property.SearchPattern; propToUpdate.ReplacePattern = property.ReplacePattern; context.SaveChanges(); } } } else { throw new ArgumentException("Unknown type supplied"); } } catch (Exception ex) { Log.Error($"Unable to persist target changes on {sender.GetType()}, Error: {ex.Message}"); Log.Error($"Stack Trace: {ex.StackTrace}"); } }
/// <summary> /// Polls CM for current status via call to http://host:port/status page /// </summary> /// <param name="hostToCheck">The host on which the CM is installed</param> /// <param name="cmToCheck">The CM to poll</param> /// <returns>Task<HttpStatusCode> containing CM status, though this is backup functionality, expected use is the event PollComplete</returns> public static async Task <HttpStatusCode> CheckCmStatus(VibesHost hostToCheck, VibesCm cmToCheck, int hashCode) { HttpStatusCode statusCode = HttpStatusCode.ServiceUnavailable; try { if (hostToCheck == null || cmToCheck == null) { string missingParameter = hostToCheck == null ? "Selected Host" : "Selected CM"; throw new Exception($"Error polling CM, Missing parameter {missingParameter}"); } int.TryParse(cmToCheck.CmPort, out int port); var builder = new UriBuilder("http", hostToCheck.Url, port) { Path = "status" }; Uri uri = builder.Uri; var response = await StaticHttpClient.GetAsync(uri); if (response.IsSuccessStatusCode) { var responseBody = await response.Content.ReadAsStringAsync(); if (!string.IsNullOrEmpty(responseBody) && responseBody.Contains("CM = Alive!")) { statusCode = HttpStatusCode.OK; } } else { statusCode = HttpStatusCode.ServiceUnavailable; } } catch (Exception ex) { // HTTP timeout, CM offline if (ex.Message.Contains("A task was canceled.")) { Log.Information($"HTTP error: Request to {cmToCheck.CmResourceName} timed out"); statusCode = HttpStatusCode.RequestTimeout; OnPollComplete(cmToCheck, statusCode, hashCode); return(statusCode); } // Unkonwn Host else if (ex.InnerException.ToString().Contains("The remote name could not be resolved")) { Log.Information($"HTTP error: Unable to resolve hostname {cmToCheck.VibesHost.Url} for CM {cmToCheck.CmResourceName}"); statusCode = HttpStatusCode.NotFound; OnPollComplete(cmToCheck, statusCode, hashCode); return(statusCode); } // Other error else if (ex.InnerException.ToString().Contains("Unable to connect to the remote server")) { Log.Information($"CM {cmToCheck.CmResourceName} on {cmToCheck.VibesHost.Url} is reporting as offline"); statusCode = HttpStatusCode.ServiceUnavailable; OnPollComplete(cmToCheck, statusCode, hashCode); return(statusCode); } Log.Error($"Error polling CM: {ex.Message}"); Log.Error($"Stack Trace: {ex.StackTrace}"); OnPollComplete(cmToCheck, statusCode, hashCode); } OnPollComplete(cmToCheck, statusCode, hashCode); return(statusCode); }
/// <summary> /// Loads data from database /// Calls LoadBoilerplate if no data is loaded /// </summary> /// <param name="type">The GuiObjectType to load</param> /// <param name="objectId">If an object is selected prior to refreshed, it's ID can be passed so it remains selected</param> private void LoadData(GuiObjectTypes type, int objectId = 0) { try { switch (type) { case GuiObjectTypes.VibesHost: using (DataContext context = new DataContext()) { DisplayHosts.Clear(); // Nothing found, load boilerplate and terminate if (!context.EnvironmentHosts.Any()) { LoadBoilerPlate(); return; } // Load Hosts from DB foreach (VibesHost host in context.EnvironmentHosts.OrderBy(h => h.Name)) { VibesHost newHost = host.DeepCopy(); newHost.PropertyChanged += new PropertyChangedEventHandler(PersistTargetChanges); DisplayHosts.Add(newHost); } // Set GUI particulars and reload CM's SelectedHost = objectId == 0 ? DisplayHosts.FirstOrDefault() : DisplayHosts.SingleOrDefault(h => h.Id == objectId); CanEditHost = true; LoadData(GuiObjectTypes.VibesCm); } break; case GuiObjectTypes.VibesCm: using (DataContext context = new DataContext()) { DisplayCms.Clear(); // Nothing found, load boilerplate and terminate if (!context.HostCms.Any(c => c.VibesHostId == SelectedHost.Id)) { LoadBoilerPlate(); return; } // Load CMs from DB DisplayCms.Clear(); foreach (VibesCm cm in context.HostCms.Where(c => c.VibesHostId == SelectedHost.Id).OrderBy(c => c.CmResourceName)) { VibesCm newCm = cm.DeepCopy(); newCm.PropertyChanged += new PropertyChangedEventHandler(PersistTargetChanges); DisplayCms.Add(newCm); } // Set GUI particulars SelectedCm = objectId == 0 ? DisplayCms.FirstOrDefault() : DisplayCms.SingleOrDefault(c => c.Id == objectId); CanEditCm = true; } break; } } catch (Exception ex) { MessageBox.Show($"Error loading data to GUI: {ex.Message}"); Log.Error($"Error loading data to GUI: {ex.Message}"); } }