xenadmin/XenAdmin/Dialogs/HealthCheck/HealthCheckOverviewDialog.cs
Mihaela Stoica 67e4e2113f CA-208829: Unexpected error if connection lost while health check dialog open
- Invoke on the main thread

Signed-off-by: Mihaela Stoica <mihaela.stoica@citrix.com>
2016-05-23 14:11:03 +01:00

458 lines
20 KiB
C#

/* Copyright (c) Citrix Systems Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using XenAdmin.Actions;
using XenAdmin.Core;
using XenAdmin.Dialogs.VMProtectionRecovery;
using XenAdmin.Model;
using XenAdmin.Network;
using XenAPI;
namespace XenAdmin.Dialogs.HealthCheck
{
public partial class HealthCheckOverviewDialog : XenDialogBase
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
internal override string HelpName { get { return "HealthCheckOverviewDialog"; } }
public HealthCheckOverviewDialog()
{
InitializeComponent();
Core.HealthCheck.CheckForAnalysisResultsCompleted += HealthCheck_CheckForUpdatesCompleted;
}
private Pool currentSelected = null;
private void LoadPools()
{
Program.AssertOnEventThread();
var selectedPool = currentSelected;
poolsDataGridView.SuspendLayout();
try
{
poolsDataGridView.Rows.Clear();
foreach (IXenConnection xenConnection in ConnectionsManager.XenConnectionsCopy)
{
if (!xenConnection.IsConnected || Helpers.FeatureForbidden(xenConnection, Host.RestrictHealthCheck))
continue;
var pool = Helpers.GetPoolOfOne(xenConnection);
if (pool != null && poolsDataGridView.ColumnCount > 0)
{
poolsDataGridView.Rows.Add(new PoolRow(pool));
}
}
RefreshButtons();
RefreshDetailsPanel();
if (selectedPool != null)
{
foreach (DataGridViewRow row in poolsDataGridView.Rows)
{
if (row is PoolRow &&
(row as PoolRow).Pool.uuid == selectedPool.uuid)
{
poolsDataGridView.ClearSelection();
row.Selected = true;
break;
}
}
}
}
finally
{
poolsDataGridView.ResumeLayout();
}
}
void Pool_BatchCollectionChanged(object sender, EventArgs e)
{
Program.Invoke(Program.MainWindow, LoadPools);
}
#region PoolRow
private class PoolRow : DataGridViewRow
{
private DataGridViewTextAndImageCell _nameCell = new DataGridViewTextAndImageCell();
private DataGridViewTextAndImageCell _statusCell = new DataGridViewTextAndImageCell();
public readonly Pool Pool;
public PoolRow(Pool pool)
{
Cells.Add(_nameCell);
Cells.Add(_statusCell);
Pool = pool;
RefreshRow();
}
public void RefreshRow()
{
_nameCell.Value = Pool.Name;
_nameCell.Image = null;
_statusCell.Value = Pool.HealthCheckSettings.StatusDescription;
_statusCell.Image = Pool.HealthCheckSettings.Status != HealthCheckStatus.Enabled || !Pool.HealthCheckSettings.HasAnalysisResult
? null
: GetSeverityImage(Pool.HealthCheckSettings);
}
private Image GetSeverityImage(HealthCheckSettings healthCheckSettings)
{
if (healthCheckSettings.ReportAnalysisIssuesDetected == 0)
return Properties.Resources._000_Tick_h32bit_16;
switch (healthCheckSettings.ReportAnalysisSeverity)
{
case DiagnosticAlertSeverity.Error:
return Properties.Resources._000_error_h32bit_16;
case DiagnosticAlertSeverity.Warning:
return Properties.Resources._000_Alert2_h32bit_16;
default:
return Properties.Resources._000_Info3_h32bit_16;
}
}
}
#endregion
private void RefreshButtons()
{
if (poolsDataGridView.SelectedRows.Count == 1 && poolsDataGridView.SelectedRows[0] is PoolRow)
{
currentSelected = (Pool)((PoolRow)poolsDataGridView.SelectedRows[0]).Pool;
}
else
{
if (poolsDataGridView.SelectedRows.Count == 0)
currentSelected = null;
}
poolDetailsPanel.Visible = (currentSelected != null);
}
private void RefreshDetailsPanel()
{
if (poolsDataGridView.SelectedRows.Count != 1 || !(poolsDataGridView.SelectedRows[0] is PoolRow))
{
poolNameLabel.Text = "";
return;
}
var poolRow = (PoolRow)poolsDataGridView.SelectedRows[0];
var healthcheckSettings = poolRow.Pool.HealthCheckSettings;
poolNameLabel.Text = poolRow.Pool.Name.Ellipsise(120);
scheduleLabel.Text = GetScheduleDescription(healthcheckSettings);
lastUploadLabel.Visible = lastUploadDateLabel.Visible = !string.IsNullOrEmpty(healthcheckSettings.LastSuccessfulUpload);
lastUploadDateLabel.Text = GetLastUploadDescription(healthcheckSettings);
// show the "Last failed upload" if we have a failed upload AND
// there is no successful upload or the failed upload happened after a successful upload
var lastFailedUploadTime = healthcheckSettings.LastFailedUploadTime;
bool showFailedUpload = lastFailedUploadTime > DateTime.MinValue
&& (string.IsNullOrEmpty(healthcheckSettings.LastSuccessfulUpload) || lastFailedUploadTime > healthcheckSettings.LastSuccessfulUploadTime);
failedUploadLabel.Visible = failedUploadDateLabel.Visible = showFailedUpload;
if (showFailedUpload)
failedUploadDateLabel.Text = HelpersGUI.DateTimeToString(lastFailedUploadTime.ToLocalTime(), Messages.DATEFORMAT_DMY_HM, true);
UpdateButtonsVisibility(poolRow.Pool);
healthCheckStatusPanel.Visible = poolRow.Pool.HealthCheckSettings.Status == HealthCheckStatus.Enabled;
notEnrolledPanel.Visible = poolRow.Pool.HealthCheckSettings.Status != HealthCheckStatus.Enabled;
UpdateUploadRequestDescription(poolRow.Pool.HealthCheckSettings);
UpdateAnalysisResult(poolRow.Pool.HealthCheckSettings);
}
public string GetScheduleDescription(HealthCheckSettings healthCheckSettings)
{
{
var time = new DateTime(1900, 1, 1, healthCheckSettings.TimeOfDay, 0, 0);
return healthCheckSettings.Status == HealthCheckStatus.Enabled
? string.Format(Messages.HEALTHCHECK_SCHEDULE_DESCRIPTION, healthCheckSettings.IntervalInWeeks,
HelpersGUI.DayOfWeekToString(healthCheckSettings.DayOfWeek, true),
HelpersGUI.DateTimeToString(time, Messages.DATEFORMAT_HM, true))
: string.Empty;
}
}
public void UpdateUploadRequestDescription(HealthCheckSettings healthCheckSettings)
{
{
if (!healthCheckSettings.CanRequestNewUpload)
{
uploadRequestLinkLabel.Text = string.Format(Messages.HEALTHCHECK_ON_DEMAND_REQUESTED_AT,
HelpersGUI.DateTimeToString(healthCheckSettings.NewUploadRequestTime.ToLocalTime(),
Messages.DATEFORMAT_HM, true));
uploadRequestLinkLabel.LinkArea = new LinkArea(0, 0);
return;
}
uploadRequestLinkLabel.Text = Messages.HEALTHCHECK_ON_DEMAND_REQUEST;
uploadRequestLinkLabel.LinkArea = new LinkArea(0, uploadRequestLinkLabel.Text.Length);
}
}
public string GetLastUploadDescription(HealthCheckSettings healthCheckSettings)
{
if (!string.IsNullOrEmpty(healthCheckSettings.LastSuccessfulUpload))
{
DateTime lastSuccessfulUpload;
if (HealthCheckSettings.TryParseStringToDateTime(healthCheckSettings.LastSuccessfulUpload, out lastSuccessfulUpload))
{
return HelpersGUI.DateTimeToString(lastSuccessfulUpload.ToLocalTime(), Messages.DATEFORMAT_DMY_HM, true);
}
}
return string.Empty;
}
public void UpdateAnalysisResult(HealthCheckSettings healthCheckSettings)
{
issuesLabel.Text = healthCheckSettings.StatusDescription;
ReportAnalysisLinkLabel.Visible = healthCheckSettings.HasAnalysisResult;
if (healthCheckSettings.HasAnalysisResult)
switch (healthCheckSettings.ReportAnalysisSeverity)
{
case DiagnosticAlertSeverity.Error:
issuesLabel.ForeColor = Color.Red;
break;
case DiagnosticAlertSeverity.Warning:
issuesLabel.ForeColor = Color.OrangeRed;
break;
default:
issuesLabel.ForeColor =
healthCheckSettings.ReportAnalysisIssuesDetected > 0 ? SystemColors.ControlText : Color.Green;
break;
}
else
{
issuesLabel.ForeColor = SystemColors.ControlText;
}
refreshLinkLabel.Visible = healthCheckSettings.HasUpload && !healthCheckSettings.HasAnalysisResult;
if (healthCheckSettings.HasOldAnalysisResult)
{
previousUploadPanel.Visible = healthCheckSettings.HasOldAnalysisResult;
DateTime previousUpload;
if (HealthCheckSettings.TryParseStringToDateTime(healthCheckSettings.ReportAnalysisUploadTime,
out previousUpload))
{
previousUploadDateLabel.Text = HelpersGUI.DateTimeToString(previousUpload.ToLocalTime(),
Messages.DATEFORMAT_DMY_HM, true);
}
}
else
{
previousUploadPanel.Visible = false;
}
}
public void UpdateButtonsVisibility(Pool pool)
{
refreshLinkLabel.Visible =
editLinkLabel.Visible =
disableLinkLabel.Visible =
uploadRequestLinkLabel.Visible =
enrollNowLinkLabel.Visible = Core.HealthCheck.PassedRbacChecks(pool.Connection);
}
private void HealthCheckOverviewDialog_Load(object sender, EventArgs e)
{
LoadPools();
foreach (IXenConnection xenConnection in ConnectionsManager.XenConnectionsCopy)
{
xenConnection.Cache.RegisterBatchCollectionChanged<Pool>(Pool_BatchCollectionChanged);
}
showAgainCheckBox.Checked = Properties.Settings.Default.ShowHealthCheckEnrollmentReminder;
}
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
RefreshButtons();
RefreshDetailsPanel();
}
private void HealthCheckOOverviewDialog_FormClosed(object sender, FormClosedEventArgs e)
{
foreach (IXenConnection xenConnection in ConnectionsManager.XenConnectionsCopy)
{
xenConnection.Cache.DeregisterBatchCollectionChanged<Pool>(Pool_BatchCollectionChanged);
}
}
private void buttonCancel_Click(object sender, EventArgs e)
{
Close();
}
private void editlinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
if (poolsDataGridView.SelectedRows.Count != 1 || !(poolsDataGridView.SelectedRows[0] is PoolRow))
return;
var poolRow = (PoolRow)poolsDataGridView.SelectedRows[0];
new HealthCheckSettingsDialog(poolRow.Pool, false).ShowDialog(this);
}
public DialogResult ShowDialog(IWin32Window parent, List<IXenObject> selectedItems)
{
SelectPool(selectedItems);
return ShowDialog(parent);
}
public void RefreshView(List<IXenObject> selectedItems)
{
SelectPool(selectedItems);
LoadPools();
}
private void SelectPool(List<IXenObject> selectedItems)
{
IXenObject xo = selectedItems.Count > 0 ? selectedItems.FirstOrDefault() : null;
if (xo is Pool)
currentSelected = xo as Pool;
}
private void enrollNowLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
if (poolsDataGridView.SelectedRows.Count != 1 || !(poolsDataGridView.SelectedRows[0] is PoolRow))
return;
var poolRow = (PoolRow)poolsDataGridView.SelectedRows[0];
new HealthCheckSettingsDialog(poolRow.Pool, true).ShowDialog(this);
}
private void uploadRequestLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
if (poolsDataGridView.SelectedRows.Count != 1 || !(poolsDataGridView.SelectedRows[0] is PoolRow))
return;
var poolRow = (PoolRow)poolsDataGridView.SelectedRows[0];
var healthCheckSettings = poolRow.Pool.HealthCheckSettings;
if (healthCheckSettings.CanRequestNewUpload)
{
healthCheckSettings.NewUploadRequest = HealthCheckSettings.DateTimeToString(DateTime.UtcNow);
var token = healthCheckSettings.GetSecretyInfo(poolRow.Pool.Connection, HealthCheckSettings.UPLOAD_TOKEN_SECRET);
var diagnosticToken = healthCheckSettings.GetSecretyInfo(poolRow.Pool.Connection, HealthCheckSettings.UPLOAD_TOKEN_SECRET);
var user = healthCheckSettings.GetSecretyInfo(poolRow.Pool.Connection, HealthCheckSettings.UPLOAD_CREDENTIAL_USER_SECRET);
var password = healthCheckSettings.GetSecretyInfo(poolRow.Pool.Connection, HealthCheckSettings.UPLOAD_CREDENTIAL_PASSWORD_SECRET);
new SaveHealthCheckSettingsAction(poolRow.Pool, healthCheckSettings, token, diagnosticToken, user, password, false).RunAsync();
}
}
private void showAgainCheckBox_CheckedChanged(object sender, EventArgs e)
{
if (Properties.Settings.Default.ShowHealthCheckEnrollmentReminder != showAgainCheckBox.Checked)
{
Properties.Settings.Default.ShowHealthCheckEnrollmentReminder = showAgainCheckBox.Checked;
Settings.TrySaveSettings();
}
}
private void disableLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
if (poolsDataGridView.SelectedRows.Count != 1 || !(poolsDataGridView.SelectedRows[0] is PoolRow))
return;
var poolRow = (PoolRow)poolsDataGridView.SelectedRows[0];
if (poolRow.Pool == null)
return;
var healthCheckSettings = poolRow.Pool.HealthCheckSettings;
if (healthCheckSettings.Status == HealthCheckStatus.Enabled)
{
string msg = Helpers.GetPool(poolRow.Pool.Connection) == null
? Messages.CONFIRM_DISABLE_HEALTH_CHECK_SERVER
: Messages.CONFIRM_DISABLE_HEALTH_CHECK_POOL;
using (var dlg = new ThreeButtonDialog(new ThreeButtonDialog.Details(null, msg, Messages.XENCENTER),
ThreeButtonDialog.ButtonYes, ThreeButtonDialog.ButtonNo))
{
if (dlg.ShowDialog(this) != DialogResult.Yes)
return;
}
healthCheckSettings.Status = HealthCheckStatus.Disabled;
new SaveHealthCheckSettingsAction(poolRow.Pool, healthCheckSettings, null, null, null, null, false).RunAsync();
}
}
private void ReportAnalysisLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
if (poolsDataGridView.SelectedRows.Count != 1 || !(poolsDataGridView.SelectedRows[0] is PoolRow))
return;
var poolRow = (PoolRow)poolsDataGridView.SelectedRows[0];
if (poolRow.Pool == null)
return;
var url = poolRow.Pool.HealthCheckSettings.GetReportAnalysisLink(Registry.HealthCheckDiagnosticDomainName);
if (!string.IsNullOrEmpty(url))
Program.OpenURL(url);
}
private void viewReportLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
if (poolsDataGridView.SelectedRows.Count != 1 || !(poolsDataGridView.SelectedRows[0] is PoolRow))
return;
var poolRow = (PoolRow)poolsDataGridView.SelectedRows[0];
if (poolRow.Pool == null)
return;
var url = poolRow.Pool.HealthCheckSettings.GetReportAnalysisLink(Registry.HealthCheckDiagnosticDomainName);
if (!string.IsNullOrEmpty(url))
Program.OpenURL(url);
}
private void refreshLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
var poolRow = (PoolRow)poolsDataGridView.SelectedRows[0];
if (poolRow.Pool == null)
return;
Core.HealthCheck.CheckForAnalysisResults(poolRow.Pool.Connection, false);
}
private void HealthCheck_CheckForUpdatesCompleted(bool succeeded)
{
Program.Invoke(Program.MainWindow, LoadPools);
}
private void PolicyStatementLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
new HealthCheckPolicyStatementDialog().ShowDialog(this);
}
}
}